mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-30 09:54:45 +00:00
Remove := with var and :: with const
This commit is contained in:
211
code/demo.odin
211
code/demo.odin
@@ -1,201 +1,16 @@
|
||||
//
|
||||
// Odin v0.3 Demo
|
||||
//
|
||||
|
||||
#import "fmt.odin";
|
||||
#import "atomics.odin";
|
||||
#import "bits.odin";
|
||||
#import "math.odin";
|
||||
#import "mem.odin";
|
||||
#import "opengl.odin";
|
||||
#import "strconv.odin";
|
||||
#import "strings.odin";
|
||||
#import "sync.odin";
|
||||
#import "types.odin";
|
||||
#import "utf8.odin";
|
||||
#import "utf16.odin";
|
||||
|
||||
main :: proc() {
|
||||
/*
|
||||
Minor features
|
||||
--------------
|
||||
|
||||
* Lexical sugar
|
||||
- ≠, ≤, ≥
|
||||
* Label syntax change
|
||||
name: for {
|
||||
break name;
|
||||
}
|
||||
* `#no_alias` (replacing keyword `no_alias`)
|
||||
* `#ordered` reimplemented
|
||||
* "bits.odin"
|
||||
* `default:` is replaced with `case:`
|
||||
* XOR for booleans
|
||||
* Bug fixes
|
||||
* Removed Quaternion types quaternion128 & quaternion256
|
||||
* `rune` is a core type - allowing for extra type information at runtime
|
||||
* `byte` is removed - use `u8` instead (which it was an alias for)
|
||||
*/
|
||||
|
||||
// 128 bit integers
|
||||
{
|
||||
x: u128 = 1234567890123;
|
||||
y: u128 = 9876543210123;
|
||||
z := (x * y) + x + y;
|
||||
fmt.println(z);
|
||||
|
||||
a: i128 = +1234567890123;
|
||||
b: i128 = -9876543210123;
|
||||
c := (a * b) + a + b;
|
||||
fmt.println(c);
|
||||
}
|
||||
|
||||
// Divisor based modulo operator
|
||||
{
|
||||
x: i128 = -15;
|
||||
y: i128 = 2;
|
||||
|
||||
fmt.println(x % y); // Dividend based
|
||||
fmt.println(x %% y); // Divisor based
|
||||
|
||||
// a %% b == ((a % b) + b) % b;
|
||||
}
|
||||
|
||||
// Casting syntax
|
||||
{
|
||||
// Casting operations have had their syntax change for simplicity and consistency
|
||||
// Original:
|
||||
// Regular cast: `cast(type) expr`
|
||||
// Bit cast: `transmute(type) expr`
|
||||
// Union cast: `union_cast(type) expr`
|
||||
|
||||
// Regular Cast
|
||||
f: f32 = 123.321;
|
||||
i := i32(f); // type(expr)
|
||||
|
||||
|
||||
// Bit cast
|
||||
fbits := transmute(u32, f);
|
||||
|
||||
|
||||
|
||||
// Type assertion - replaces `union_cast`
|
||||
Entity :: union {
|
||||
id: u64,
|
||||
position: [vector 2]f32,
|
||||
name: string,
|
||||
|
||||
Tree{leaf_count: int},
|
||||
Frog{ribbit_volume: f32},
|
||||
}
|
||||
|
||||
e: Entity;
|
||||
e = Entity.Frog{ribbit_volume = 0.5, name = "Trevor"};
|
||||
|
||||
if frog, ok := e.(Entity.Frog); ok {
|
||||
fmt.printf("%s the frog ribbits at %f\n", frog.name, frog.ribbit_volume);
|
||||
}
|
||||
|
||||
// Panics if the type assertion fails
|
||||
frog := e.(Entity.Frog);
|
||||
|
||||
{
|
||||
// Type assertion can also be applied to `any`
|
||||
foo: any = 123;
|
||||
if i, ok := foo.(int); ok {
|
||||
fmt.println("Foo =", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Syntax changes
|
||||
{
|
||||
// Originally `^` was used to represent pointer types, pointer dereferencing, and addressing of variables
|
||||
// The addressing of variable operation is not represented with `&`
|
||||
// This is to make sure the concept of a pointer type is separate from that of a addressing
|
||||
// it is also used for familiarity coming from other C-like languages
|
||||
x: int = 123;
|
||||
y: ^int = &x;
|
||||
z: int = y^;
|
||||
|
||||
// This change also allows type casting to not require parentheses around the type for pointer evaluation
|
||||
// and consitency with other operations
|
||||
|
||||
data := rawptr(&x);
|
||||
int_ptr := ^int(data);
|
||||
|
||||
array: [10]int; // Type of the left
|
||||
x = array[0]; // Usage on the right
|
||||
|
||||
ptr: ^int = &z; // Type of the left
|
||||
x = ptr^; // Usage on the right
|
||||
|
||||
|
||||
|
||||
// Minor addition - member access through number
|
||||
TupleLike :: struct{int, f32, string}; // Fields all anonymous
|
||||
t: TupleLike;
|
||||
t.0 = 123;
|
||||
t.1 = 46.432;
|
||||
t.2 = "Foo";
|
||||
fmt.println(t);
|
||||
}
|
||||
|
||||
// Bit fields
|
||||
{
|
||||
BoxProps :: bit_field {
|
||||
opaque: 1,
|
||||
fill_colour: 3,
|
||||
_: 4,
|
||||
show_border: 1,
|
||||
_: 3,
|
||||
border_style: 2,
|
||||
_: 2,
|
||||
width: 4,
|
||||
height: 4,
|
||||
};
|
||||
|
||||
props: BoxProps;
|
||||
props.fill_colour = 4;
|
||||
props.show_border = 1;
|
||||
props.width = 12;
|
||||
props.height = 10;
|
||||
|
||||
fmt.printf("Width: %d, Height: %d\n", props.width, props.height);
|
||||
|
||||
|
||||
|
||||
Float32Data :: bit_field #align 4 {
|
||||
fraction: 23,
|
||||
exponent: 8,
|
||||
sign: 1,
|
||||
}
|
||||
|
||||
f: f32 = -123.321;
|
||||
data := transmute(Float32Data, f);
|
||||
bits := transmute(u32, f);
|
||||
fmt.printf("%#05x %#02x %v\n", data.fraction, data.exponent, bool(data.sign));
|
||||
fmt.printf("%#08x\n", bits);
|
||||
}
|
||||
|
||||
// Naming convention
|
||||
{
|
||||
// Odin has finally chose an official naming convention
|
||||
// In general, PascalCase for types and snake_case for values
|
||||
|
||||
// Import Name: snake_case (but prefer single word)
|
||||
// Types: PascalCase
|
||||
// Union Variants: PascalCase
|
||||
// Enum Values: PascalCase
|
||||
// Procedures: snake_case
|
||||
// Local Variables: snake_case
|
||||
// Field Values: snake_case
|
||||
// Constant Variables: SCREAMING_SNAKE_CASE
|
||||
}
|
||||
|
||||
// Goals for v0.4 and further
|
||||
// * Compile as C++ and use some of its constructs for sanity e.g. overloading
|
||||
// - Safe array with bounds checking
|
||||
// - Map type for self documentation
|
||||
// - u128 i128 acting like core types
|
||||
// * Context system implemented as Implicit Parameter Passing (IPP) rather than Thread Local Storage (TLS)
|
||||
// * Parameter Polymorphism
|
||||
// - Type parameter is procedures and types
|
||||
// * Decide upon a declaration syntax
|
||||
// - Current Style (name: type;) vs Prefix Style (var name: type;)
|
||||
// * Import system with a "solution" for packages/modules/libraries
|
||||
// * Better foreign interfacing with C (and maybe C++)
|
||||
// - Foreign variables
|
||||
// * Documentation Generation System for code
|
||||
// * General Documentation for Odin
|
||||
// * Attributes
|
||||
const main = proc() {
|
||||
fmt.println("Hello");
|
||||
}
|
||||
|
||||
@@ -24,19 +24,19 @@
|
||||
|
||||
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
||||
// The compiler relies upon this _exact_ order
|
||||
TypeInfoEnumValue :: raw_union {
|
||||
const TypeInfoEnumValue = raw_union {
|
||||
f: f64,
|
||||
i: i128,
|
||||
}
|
||||
// NOTE(bill): This must match the compiler's
|
||||
CallingConvention :: enum {
|
||||
const CallingConvention = enum {
|
||||
Odin = 0,
|
||||
C = 1,
|
||||
Std = 2,
|
||||
Fast = 3,
|
||||
}
|
||||
|
||||
TypeInfoRecord :: struct #ordered {
|
||||
const TypeInfoRecord = struct #ordered {
|
||||
types: []^TypeInfo,
|
||||
names: []string,
|
||||
offsets: []int, // offsets may not be used in tuples
|
||||
@@ -46,7 +46,7 @@ TypeInfoRecord :: struct #ordered {
|
||||
custom_align: bool,
|
||||
}
|
||||
|
||||
TypeInfo :: union {
|
||||
const TypeInfo = union {
|
||||
size: int,
|
||||
align: int,
|
||||
|
||||
@@ -109,16 +109,16 @@ TypeInfo :: union {
|
||||
|
||||
// NOTE(bill): only the ones that are needed (not all types)
|
||||
// This will be set by the compiler
|
||||
__type_table: []TypeInfo;
|
||||
var __type_table: []TypeInfo;
|
||||
|
||||
__argv__: ^^u8;
|
||||
__argc__: i32;
|
||||
var __argv__: ^^u8;
|
||||
var __argc__: i32;
|
||||
|
||||
type_info_base :: proc(info: ^TypeInfo) -> ^TypeInfo {
|
||||
const type_info_base = proc(info: ^TypeInfo) -> ^TypeInfo {
|
||||
if info == nil {
|
||||
return nil;
|
||||
}
|
||||
base := info;
|
||||
var base = info;
|
||||
match i in base {
|
||||
case TypeInfo.Named:
|
||||
base = i.base;
|
||||
@@ -127,11 +127,11 @@ type_info_base :: proc(info: ^TypeInfo) -> ^TypeInfo {
|
||||
}
|
||||
|
||||
|
||||
type_info_base_without_enum :: proc(info: ^TypeInfo) -> ^TypeInfo {
|
||||
const type_info_base_without_enum = proc(info: ^TypeInfo) -> ^TypeInfo {
|
||||
if info == nil {
|
||||
return nil;
|
||||
}
|
||||
base := info;
|
||||
var base = info;
|
||||
match i in base {
|
||||
case TypeInfo.Named:
|
||||
base = i.base;
|
||||
@@ -143,30 +143,30 @@ type_info_base_without_enum :: proc(info: ^TypeInfo) -> ^TypeInfo {
|
||||
|
||||
|
||||
|
||||
assume :: proc(cond: bool) #foreign __llvm_core "llvm.assume";
|
||||
const assume = proc(cond: bool) #foreign __llvm_core "llvm.assume";
|
||||
|
||||
__debug_trap :: proc() #foreign __llvm_core "llvm.debugtrap";
|
||||
__trap :: proc() #foreign __llvm_core "llvm.trap";
|
||||
read_cycle_counter :: proc() -> u64 #foreign __llvm_core "llvm.readcyclecounter";
|
||||
const __debug_trap = proc() #foreign __llvm_core "llvm.debugtrap";
|
||||
const __trap = proc() #foreign __llvm_core "llvm.trap";
|
||||
const read_cycle_counter = proc() -> u64 #foreign __llvm_core "llvm.readcyclecounter";
|
||||
|
||||
|
||||
// IMPORTANT NOTE(bill): Must be in this order (as the compiler relies upon it)
|
||||
AllocatorMode :: enum u8 {
|
||||
const AllocatorMode = enum u8 {
|
||||
Alloc,
|
||||
Free,
|
||||
FreeAll,
|
||||
Resize,
|
||||
}
|
||||
AllocatorProc :: #type proc(allocator_data: rawptr, mode: AllocatorMode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr;
|
||||
Allocator :: struct #ordered {
|
||||
const AllocatorProc = type proc(allocator_data: rawptr, mode: AllocatorMode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr;
|
||||
const Allocator = struct #ordered {
|
||||
procedure: AllocatorProc,
|
||||
data: rawptr,
|
||||
}
|
||||
|
||||
|
||||
Context :: struct #ordered {
|
||||
const Context = struct #ordered {
|
||||
thread_id: int,
|
||||
|
||||
allocator: Allocator,
|
||||
@@ -175,14 +175,14 @@ Context :: struct #ordered {
|
||||
user_index: int,
|
||||
}
|
||||
|
||||
#thread_local __context: Context;
|
||||
#thread_local var __context: Context;
|
||||
|
||||
|
||||
DEFAULT_ALIGNMENT :: align_of([vector 4]f32);
|
||||
const DEFAULT_ALIGNMENT = align_of([vector 4]f32);
|
||||
|
||||
|
||||
__check_context :: proc() {
|
||||
c := &__context;
|
||||
const __check_context = proc() {
|
||||
var c = &__context;
|
||||
|
||||
if c.allocator.procedure == nil {
|
||||
c.allocator = default_allocator();
|
||||
@@ -192,15 +192,15 @@ __check_context :: proc() {
|
||||
}
|
||||
}
|
||||
|
||||
alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT); }
|
||||
const alloc = proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT); }
|
||||
|
||||
alloc_align :: proc(size, alignment: int) -> rawptr #inline {
|
||||
const alloc_align = proc(size, alignment: int) -> rawptr #inline {
|
||||
__check_context();
|
||||
a := context.allocator;
|
||||
var a = context.allocator;
|
||||
return a.procedure(a.data, AllocatorMode.Alloc, size, alignment, nil, 0, 0);
|
||||
}
|
||||
|
||||
free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline {
|
||||
const free_ptr_with_allocator = proc(a: Allocator, ptr: rawptr) #inline {
|
||||
if ptr == nil {
|
||||
return;
|
||||
}
|
||||
@@ -210,28 +210,28 @@ free_ptr_with_allocator :: proc(a: Allocator, ptr: rawptr) #inline {
|
||||
a.procedure(a.data, AllocatorMode.Free, 0, 0, ptr, 0, 0);
|
||||
}
|
||||
|
||||
free_ptr :: proc(ptr: rawptr) #inline {
|
||||
const free_ptr = proc(ptr: rawptr) #inline {
|
||||
__check_context();
|
||||
free_ptr_with_allocator(context.allocator, ptr);
|
||||
}
|
||||
|
||||
free_all :: proc() #inline {
|
||||
const free_all = proc() #inline {
|
||||
__check_context();
|
||||
a := context.allocator;
|
||||
var a = context.allocator;
|
||||
a.procedure(a.data, AllocatorMode.FreeAll, 0, 0, nil, 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 {
|
||||
const resize = proc(ptr: rawptr, old_size, new_size: int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT); }
|
||||
const resize_align = proc(ptr: rawptr, old_size, new_size, alignment: int) -> rawptr #inline {
|
||||
__check_context();
|
||||
a := context.allocator;
|
||||
var a = context.allocator;
|
||||
return a.procedure(a.data, AllocatorMode.Resize, new_size, alignment, ptr, old_size, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
|
||||
const default_resize_align = proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
|
||||
if old_memory == nil {
|
||||
return alloc_align(new_size, alignment);
|
||||
}
|
||||
@@ -245,7 +245,7 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment:
|
||||
return old_memory;
|
||||
}
|
||||
|
||||
new_memory := alloc_align(new_size, alignment);
|
||||
var new_memory = alloc_align(new_size, alignment);
|
||||
if new_memory == nil {
|
||||
return nil;
|
||||
}
|
||||
@@ -256,7 +256,7 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment:
|
||||
}
|
||||
|
||||
|
||||
default_allocator_proc :: proc(allocator_data: rawptr, mode: AllocatorMode,
|
||||
const default_allocator_proc = proc(allocator_data: rawptr, mode: AllocatorMode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
||||
using AllocatorMode;
|
||||
@@ -273,7 +273,7 @@ default_allocator_proc :: proc(allocator_data: rawptr, mode: AllocatorMode,
|
||||
// NOTE(bill): Does nothing
|
||||
|
||||
case Resize:
|
||||
ptr := os.heap_resize(old_memory, size);
|
||||
var ptr = os.heap_resize(old_memory, size);
|
||||
assert(ptr != nil);
|
||||
return ptr;
|
||||
}
|
||||
@@ -281,7 +281,7 @@ default_allocator_proc :: proc(allocator_data: rawptr, mode: AllocatorMode,
|
||||
return nil;
|
||||
}
|
||||
|
||||
default_allocator :: proc() -> Allocator {
|
||||
const default_allocator = proc() -> Allocator {
|
||||
return Allocator{
|
||||
procedure = default_allocator_proc,
|
||||
data = nil,
|
||||
@@ -296,7 +296,7 @@ default_allocator :: proc() -> Allocator {
|
||||
|
||||
|
||||
|
||||
__string_eq :: proc(a, b: string) -> bool {
|
||||
const __string_eq = proc(a, b: string) -> bool {
|
||||
if len(a) != len(b) {
|
||||
return false;
|
||||
}
|
||||
@@ -309,34 +309,34 @@ __string_eq :: proc(a, b: string) -> bool {
|
||||
return __string_cmp(a, b) == 0;
|
||||
}
|
||||
|
||||
__string_cmp :: proc(a, b: string) -> int {
|
||||
const __string_cmp = proc(a, b: string) -> int {
|
||||
return __mem_compare(&a[0], &b[0], min(len(a), len(b)));
|
||||
}
|
||||
|
||||
__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; }
|
||||
const __string_ne = proc(a, b: string) -> bool #inline { return !__string_eq(a, b); }
|
||||
const __string_lt = proc(a, b: string) -> bool #inline { return __string_cmp(a, b) < 0; }
|
||||
const __string_gt = proc(a, b: string) -> bool #inline { return __string_cmp(a, b) > 0; }
|
||||
const __string_le = proc(a, b: string) -> bool #inline { return __string_cmp(a, b) <= 0; }
|
||||
const __string_ge = proc(a, b: string) -> bool #inline { return __string_cmp(a, b) >= 0; }
|
||||
|
||||
|
||||
__complex64_eq :: proc(a, b: complex64) -> bool #inline { return real(a) == real(b) && imag(a) == imag(b); }
|
||||
__complex64_ne :: proc(a, b: complex64) -> bool #inline { return real(a) != real(b) || imag(a) != imag(b); }
|
||||
const __complex64_eq = proc(a, b: complex64) -> bool #inline { return real(a) == real(b) && imag(a) == imag(b); }
|
||||
const __complex64_ne = proc(a, b: complex64) -> bool #inline { return real(a) != real(b) || imag(a) != imag(b); }
|
||||
|
||||
__complex128_eq :: proc(a, b: complex128) -> bool #inline { return real(a) == real(b) && imag(a) == imag(b); }
|
||||
__complex128_ne :: proc(a, b: complex128) -> bool #inline { return real(a) != real(b) || imag(a) != imag(b); }
|
||||
const __complex128_eq = proc(a, b: complex128) -> bool #inline { return real(a) == real(b) && imag(a) == imag(b); }
|
||||
const __complex128_ne = proc(a, b: complex128) -> bool #inline { return real(a) != real(b) || imag(a) != imag(b); }
|
||||
|
||||
__assert :: proc(file: string, line, column: int, msg: string) #inline {
|
||||
const __assert = proc(file: string, line, column: int, msg: string) #inline {
|
||||
fmt.fprintf(os.stderr, "%s(%d:%d) Runtime assertion: %s\n",
|
||||
file, line, column, msg);
|
||||
__debug_trap();
|
||||
}
|
||||
__panic :: proc(file: string, line, column: int, msg: string) #inline {
|
||||
const __panic = proc(file: string, line, column: int, msg: string) #inline {
|
||||
fmt.fprintf(os.stderr, "%s(%d:%d) Panic: %s\n",
|
||||
file, line, column, msg);
|
||||
__debug_trap();
|
||||
}
|
||||
__bounds_check_error :: proc(file: string, line, column: int, index, count: int) {
|
||||
const __bounds_check_error = proc(file: string, line, column: int, index, count: int) {
|
||||
if 0 <= index && index < count {
|
||||
return;
|
||||
}
|
||||
@@ -345,7 +345,7 @@ __bounds_check_error :: proc(file: string, line, column: int, index, count: int)
|
||||
__debug_trap();
|
||||
}
|
||||
|
||||
__slice_expr_error :: proc(file: string, line, column: int, low, high, max: int) {
|
||||
const __slice_expr_error = proc(file: string, line, column: int, low, high, max: int) {
|
||||
if 0 <= low && low <= high && high <= max {
|
||||
return;
|
||||
}
|
||||
@@ -354,7 +354,7 @@ __slice_expr_error :: proc(file: string, line, column: int, low, high, max: int)
|
||||
__debug_trap();
|
||||
}
|
||||
|
||||
__substring_expr_error :: proc(file: string, line, column: int, low, high: int) {
|
||||
const __substring_expr_error = proc(file: string, line, column: int, low, high: int) {
|
||||
if 0 <= low && low <= high {
|
||||
return;
|
||||
}
|
||||
@@ -362,7 +362,7 @@ __substring_expr_error :: proc(file: string, line, column: int, low, high: int)
|
||||
file, line, column, low, high);
|
||||
__debug_trap();
|
||||
}
|
||||
__type_assertion_check :: proc(ok: bool, file: string, line, column: int, from, to: ^TypeInfo) {
|
||||
const __type_assertion_check = proc(ok: bool, file: string, line, column: int, from, to: ^TypeInfo) {
|
||||
if !ok {
|
||||
fmt.fprintf(os.stderr, "%s(%d:%d) Invalid type_assertion from %T to %T\n",
|
||||
file, line, column, from, to);
|
||||
@@ -370,33 +370,33 @@ __type_assertion_check :: proc(ok: bool, file: string, line, column: int, from,
|
||||
}
|
||||
}
|
||||
|
||||
__string_decode_rune :: proc(s: string) -> (rune, int) #inline {
|
||||
const __string_decode_rune = proc(s: string) -> (rune, int) #inline {
|
||||
return utf8.decode_rune(s);
|
||||
}
|
||||
|
||||
|
||||
__mem_set :: proc(data: rawptr, value: i32, len: int) -> rawptr {
|
||||
llvm_memset_64bit :: proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memset.p0i8.i64";
|
||||
const __mem_set = proc(data: rawptr, value: i32, len: int) -> rawptr {
|
||||
const llvm_memset_64bit = proc(dst: rawptr, val: u8, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memset.p0i8.i64";
|
||||
llvm_memset_64bit(data, u8(value), len, 1, false);
|
||||
return data;
|
||||
}
|
||||
__mem_zero :: proc(data: rawptr, len: int) -> rawptr {
|
||||
const __mem_zero = proc(data: rawptr, len: int) -> rawptr {
|
||||
return __mem_set(data, 0, len);
|
||||
}
|
||||
__mem_copy :: proc(dst, src: rawptr, len: int) -> rawptr {
|
||||
const __mem_copy = proc(dst, src: rawptr, len: int) -> rawptr {
|
||||
// NOTE(bill): This _must_ be implemented like C's memmove
|
||||
llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memmove.p0i8.p0i8.i64";
|
||||
const llvm_memmove_64bit = proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memmove.p0i8.p0i8.i64";
|
||||
llvm_memmove_64bit(dst, src, len, 1, false);
|
||||
return dst;
|
||||
}
|
||||
__mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr {
|
||||
const __mem_copy_non_overlapping = proc(dst, src: rawptr, len: int) -> rawptr {
|
||||
// NOTE(bill): This _must_ be implemented like C's memcpy
|
||||
llvm_memcpy_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memcpy.p0i8.p0i8.i64";
|
||||
const llvm_memcpy_64bit = proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign __llvm_core "llvm.memcpy.p0i8.p0i8.i64";
|
||||
llvm_memcpy_64bit(dst, src, len, 1, false);
|
||||
return dst;
|
||||
}
|
||||
|
||||
__mem_compare :: proc(a, b: ^u8, n: int) -> int {
|
||||
const __mem_compare = proc(a, b: ^u8, n: int) -> int {
|
||||
for i in 0..<n {
|
||||
match {
|
||||
case (a+i)^ < (b+i)^:
|
||||
@@ -408,22 +408,22 @@ __mem_compare :: proc(a, b: ^u8, n: int) -> int {
|
||||
return 0;
|
||||
}
|
||||
|
||||
__sqrt_f32 :: proc(x: f32) -> f32 #foreign __llvm_core "llvm.sqrt.f32";
|
||||
__sqrt_f64 :: proc(x: f64) -> f64 #foreign __llvm_core "llvm.sqrt.f64";
|
||||
__abs_complex64 :: proc(x: complex64) -> f32 #inline {
|
||||
r, i := real(x), imag(x);
|
||||
const __sqrt_f32 = proc(x: f32) -> f32 #foreign __llvm_core "llvm.sqrt.f32";
|
||||
const __sqrt_f64 = proc(x: f64) -> f64 #foreign __llvm_core "llvm.sqrt.f64";
|
||||
const __abs_complex64 = proc(x: complex64) -> f32 #inline {
|
||||
var r, i = real(x), imag(x);
|
||||
return __sqrt_f32(r*r + i*i);
|
||||
}
|
||||
__abs_complex128 :: proc(x: complex128) -> f64 #inline {
|
||||
r, i := real(x), imag(x);
|
||||
const __abs_complex128 = proc(x: complex128) -> f64 #inline {
|
||||
var r, i = real(x), imag(x);
|
||||
return __sqrt_f64(r*r + i*i);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
__dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int) {
|
||||
array := ^raw.DynamicArray(array_);
|
||||
const __dynamic_array_make = proc(array_: rawptr, elem_size, elem_align: int, len, cap: int) {
|
||||
var array = ^raw.DynamicArray(array_);
|
||||
__check_context();
|
||||
array.allocator = context.allocator;
|
||||
assert(array.allocator.procedure != nil);
|
||||
@@ -434,8 +434,8 @@ __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, ca
|
||||
}
|
||||
}
|
||||
|
||||
__dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int) -> bool {
|
||||
array := ^raw.DynamicArray(array_);
|
||||
const __dynamic_array_reserve = proc(array_: rawptr, elem_size, elem_align: int, cap: int) -> bool {
|
||||
var array = ^raw.DynamicArray(array_);
|
||||
|
||||
if cap <= array.cap {
|
||||
return true;
|
||||
@@ -447,11 +447,11 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap:
|
||||
}
|
||||
assert(array.allocator.procedure != nil);
|
||||
|
||||
old_size := array.cap * elem_size;
|
||||
new_size := cap * elem_size;
|
||||
allocator := array.allocator;
|
||||
var old_size = array.cap * elem_size;
|
||||
var new_size = cap * elem_size;
|
||||
var allocator = array.allocator;
|
||||
|
||||
new_data := allocator.procedure(allocator.data, AllocatorMode.Resize, new_size, elem_align, array.data, old_size, 0);
|
||||
var new_data = allocator.procedure(allocator.data, AllocatorMode.Resize, new_size, elem_align, array.data, old_size, 0);
|
||||
if new_data == nil {
|
||||
return false;
|
||||
}
|
||||
@@ -461,10 +461,10 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap:
|
||||
return true;
|
||||
}
|
||||
|
||||
__dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len: int) -> bool {
|
||||
array := ^raw.DynamicArray(array_);
|
||||
const __dynamic_array_resize = proc(array_: rawptr, elem_size, elem_align: int, len: int) -> bool {
|
||||
var array = ^raw.DynamicArray(array_);
|
||||
|
||||
ok := __dynamic_array_reserve(array_, elem_size, elem_align, len);
|
||||
var ok = __dynamic_array_reserve(array_, elem_size, elem_align, len);
|
||||
if ok {
|
||||
array.len = len;
|
||||
}
|
||||
@@ -472,53 +472,53 @@ __dynamic_array_resize :: proc(array_: rawptr, elem_size, elem_align: int, len:
|
||||
}
|
||||
|
||||
|
||||
__dynamic_array_append :: proc(array_: rawptr, elem_size, elem_align: int,
|
||||
const __dynamic_array_append = proc(array_: rawptr, elem_size, elem_align: int,
|
||||
items: rawptr, item_count: int) -> int {
|
||||
array := ^raw.DynamicArray(array_);
|
||||
var array = ^raw.DynamicArray(array_);
|
||||
|
||||
if item_count <= 0 || items == nil {
|
||||
return array.len;
|
||||
}
|
||||
|
||||
|
||||
ok := true;
|
||||
var ok = true;
|
||||
if array.cap <= array.len+item_count {
|
||||
cap := 2 * array.cap + max(8, item_count);
|
||||
var cap = 2 * array.cap + max(8, item_count);
|
||||
ok = __dynamic_array_reserve(array, elem_size, elem_align, cap);
|
||||
}
|
||||
if !ok {
|
||||
// TODO(bill): Better error handling for failed reservation
|
||||
return array.len;
|
||||
}
|
||||
data := ^u8(array.data);
|
||||
var data = ^u8(array.data);
|
||||
assert(data != nil);
|
||||
__mem_copy(data + (elem_size*array.len), items, elem_size * item_count);
|
||||
array.len += item_count;
|
||||
return array.len;
|
||||
}
|
||||
|
||||
__dynamic_array_append_nothing :: proc(array_: rawptr, elem_size, elem_align: int) -> int {
|
||||
array := ^raw.DynamicArray(array_);
|
||||
const __dynamic_array_append_nothing = proc(array_: rawptr, elem_size, elem_align: int) -> int {
|
||||
var array = ^raw.DynamicArray(array_);
|
||||
|
||||
ok := true;
|
||||
var ok = true;
|
||||
if array.cap <= array.len+1 {
|
||||
cap := 2 * array.cap + max(8, 1);
|
||||
var cap = 2 * array.cap + max(8, 1);
|
||||
ok = __dynamic_array_reserve(array, elem_size, elem_align, cap);
|
||||
}
|
||||
if !ok {
|
||||
// TODO(bill): Better error handling for failed reservation
|
||||
return array.len;
|
||||
}
|
||||
data := ^u8(array.data);
|
||||
var data = ^u8(array.data);
|
||||
assert(data != nil);
|
||||
__mem_zero(data + (elem_size*array.len), elem_size);
|
||||
array.len++;
|
||||
return array.len;
|
||||
}
|
||||
|
||||
__slice_append :: proc(slice_: rawptr, elem_size, elem_align: int,
|
||||
const __slice_append = proc(slice_: rawptr, elem_size, elem_align: int,
|
||||
items: rawptr, item_count: int) -> int {
|
||||
slice := ^raw.Slice(slice_);
|
||||
var slice = ^raw.Slice(slice_);
|
||||
|
||||
if item_count <= 0 || items == nil {
|
||||
return slice.len;
|
||||
@@ -526,7 +526,7 @@ __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int,
|
||||
|
||||
item_count = min(slice.cap-slice.len, item_count);
|
||||
if item_count > 0 {
|
||||
data := ^u8(slice.data);
|
||||
var data = ^u8(slice.data);
|
||||
assert(data != nil);
|
||||
__mem_copy(data + (elem_size*slice.len), items, elem_size * item_count);
|
||||
slice.len += item_count;
|
||||
@@ -537,9 +537,9 @@ __slice_append :: proc(slice_: rawptr, elem_size, elem_align: int,
|
||||
|
||||
// Map stuff
|
||||
|
||||
__default_hash :: proc(data: []u8) -> u128 {
|
||||
fnv128a :: proc(data: []u8) -> u128 {
|
||||
h: u128 = 0x6c62272e07bb014262b821756295c58d;
|
||||
const __default_hash = proc(data: []u8) -> u128 {
|
||||
const fnv128a = proc(data: []u8) -> u128 {
|
||||
var h: u128 = 0x6c62272e07bb014262b821756295c58d;
|
||||
for b in data {
|
||||
h = (h ~ u128(b)) * 0x1000000000000000000013b;
|
||||
}
|
||||
@@ -547,24 +547,24 @@ __default_hash :: proc(data: []u8) -> u128 {
|
||||
}
|
||||
return fnv128a(data);
|
||||
}
|
||||
__default_hash_string :: proc(s: string) -> u128 {
|
||||
const __default_hash_string = proc(s: string) -> u128 {
|
||||
return __default_hash([]u8(s));
|
||||
}
|
||||
|
||||
__INITIAL_MAP_CAP :: 16;
|
||||
const __INITIAL_MAP_CAP = 16;
|
||||
|
||||
__MapKey :: struct #ordered {
|
||||
const __MapKey = struct #ordered {
|
||||
hash: u128,
|
||||
str: string,
|
||||
}
|
||||
|
||||
__MapFindResult :: struct #ordered {
|
||||
const __MapFindResult = struct #ordered {
|
||||
hash_index: int,
|
||||
entry_prev: int,
|
||||
entry_index: int,
|
||||
}
|
||||
|
||||
__MapEntryHeader :: struct #ordered {
|
||||
const __MapEntryHeader = struct #ordered {
|
||||
key: __MapKey,
|
||||
next: int,
|
||||
/*
|
||||
@@ -572,7 +572,7 @@ __MapEntryHeader :: struct #ordered {
|
||||
*/
|
||||
}
|
||||
|
||||
__MapHeader :: struct #ordered {
|
||||
const __MapHeader = struct #ordered {
|
||||
m: ^raw.DynamicMap,
|
||||
is_key_string: bool,
|
||||
entry_size: int,
|
||||
@@ -581,18 +581,18 @@ __MapHeader :: struct #ordered {
|
||||
value_size: int,
|
||||
}
|
||||
|
||||
__dynamic_map_reserve :: proc(using header: __MapHeader, cap: int) {
|
||||
const __dynamic_map_reserve = proc(using header: __MapHeader, cap: int) {
|
||||
__dynamic_array_reserve(&m.hashes, size_of(int), align_of(int), cap);
|
||||
__dynamic_array_reserve(&m.entries, entry_size, entry_align, cap);
|
||||
}
|
||||
|
||||
__dynamic_map_rehash :: proc(using header: __MapHeader, new_count: int) {
|
||||
new_header: __MapHeader = header;
|
||||
nm: raw.DynamicMap;
|
||||
const __dynamic_map_rehash = proc(using header: __MapHeader, new_count: int) {
|
||||
var new_header: __MapHeader = header;
|
||||
var nm: raw.DynamicMap;
|
||||
new_header.m = &nm;
|
||||
|
||||
header_hashes := ^raw.DynamicArray(&header.m.hashes);
|
||||
nm_hashes := ^raw.DynamicArray(&nm.hashes);
|
||||
var header_hashes = ^raw.DynamicArray(&header.m.hashes);
|
||||
var nm_hashes = ^raw.DynamicArray(&nm.hashes);
|
||||
|
||||
__dynamic_array_resize(nm_hashes, size_of(int), align_of(int), new_count);
|
||||
__dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len);
|
||||
@@ -600,26 +600,26 @@ __dynamic_map_rehash :: proc(using header: __MapHeader, new_count: int) {
|
||||
nm.hashes[i] = -1;
|
||||
}
|
||||
|
||||
for i := 0; i < m.entries.len; i++ {
|
||||
for var i = 0; i < m.entries.len; i++ {
|
||||
if len(nm.hashes) == 0 {
|
||||
__dynamic_map_grow(new_header);
|
||||
}
|
||||
|
||||
entry_header := __dynamic_map_get_entry(header, i);
|
||||
data := ^u8(entry_header);
|
||||
var entry_header = __dynamic_map_get_entry(header, i);
|
||||
var data = ^u8(entry_header);
|
||||
|
||||
fr := __dynamic_map_find(new_header, entry_header.key);
|
||||
j := __dynamic_map_add_entry(new_header, entry_header.key);
|
||||
var fr = __dynamic_map_find(new_header, entry_header.key);
|
||||
var j = __dynamic_map_add_entry(new_header, entry_header.key);
|
||||
if fr.entry_prev < 0 {
|
||||
nm.hashes[fr.hash_index] = j;
|
||||
} else {
|
||||
e := __dynamic_map_get_entry(new_header, fr.entry_prev);
|
||||
var e = __dynamic_map_get_entry(new_header, fr.entry_prev);
|
||||
e.next = j;
|
||||
}
|
||||
|
||||
e := __dynamic_map_get_entry(new_header, j);
|
||||
var e = __dynamic_map_get_entry(new_header, j);
|
||||
e.next = fr.entry_index;
|
||||
ndata := ^u8(e);
|
||||
var ndata = ^u8(e);
|
||||
__mem_copy(ndata+value_offset, data+value_offset, value_size);
|
||||
|
||||
if __dynamic_map_full(new_header) {
|
||||
@@ -631,18 +631,18 @@ __dynamic_map_rehash :: proc(using header: __MapHeader, new_count: int) {
|
||||
header.m^ = nm;
|
||||
}
|
||||
|
||||
__dynamic_map_get :: proc(h: __MapHeader, key: __MapKey) -> rawptr {
|
||||
index := __dynamic_map_find(h, key).entry_index;
|
||||
const __dynamic_map_get = proc(h: __MapHeader, key: __MapKey) -> rawptr {
|
||||
var index = __dynamic_map_find(h, key).entry_index;
|
||||
if index >= 0 {
|
||||
data := ^u8(__dynamic_map_get_entry(h, index));
|
||||
val := data + h.value_offset;
|
||||
var data = ^u8(__dynamic_map_get_entry(h, index));
|
||||
var val = data + h.value_offset;
|
||||
return val;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
__dynamic_map_set :: proc(using h: __MapHeader, key: __MapKey, value: rawptr) {
|
||||
index: int;
|
||||
const __dynamic_map_set = proc(using h: __MapHeader, key: __MapKey, value: rawptr) {
|
||||
var index: int;
|
||||
assert(value != nil);
|
||||
|
||||
|
||||
@@ -651,22 +651,22 @@ __dynamic_map_set :: proc(using h: __MapHeader, key: __MapKey, value: rawptr) {
|
||||
__dynamic_map_grow(h);
|
||||
}
|
||||
|
||||
fr := __dynamic_map_find(h, key);
|
||||
var fr = __dynamic_map_find(h, key);
|
||||
if fr.entry_index >= 0 {
|
||||
index = fr.entry_index;
|
||||
} else {
|
||||
index = __dynamic_map_add_entry(h, key);
|
||||
if fr.entry_prev >= 0 {
|
||||
entry := __dynamic_map_get_entry(h, fr.entry_prev);
|
||||
var entry = __dynamic_map_get_entry(h, fr.entry_prev);
|
||||
entry.next = index;
|
||||
} else {
|
||||
m.hashes[fr.hash_index] = index;
|
||||
}
|
||||
}
|
||||
{
|
||||
e := __dynamic_map_get_entry(h, index);
|
||||
var e = __dynamic_map_get_entry(h, index);
|
||||
e.key = key;
|
||||
val := ^u8(e) + value_offset;
|
||||
var val = ^u8(e) + value_offset;
|
||||
__mem_copy(val, value, value_size);
|
||||
}
|
||||
|
||||
@@ -676,17 +676,17 @@ __dynamic_map_set :: proc(using h: __MapHeader, key: __MapKey, value: rawptr) {
|
||||
}
|
||||
|
||||
|
||||
__dynamic_map_grow :: proc(using h: __MapHeader) {
|
||||
new_count := max(2*m.entries.cap + 8, __INITIAL_MAP_CAP);
|
||||
const __dynamic_map_grow = proc(using h: __MapHeader) {
|
||||
var new_count = max(2*m.entries.cap + 8, __INITIAL_MAP_CAP);
|
||||
__dynamic_map_rehash(h, new_count);
|
||||
}
|
||||
|
||||
__dynamic_map_full :: proc(using h: __MapHeader) -> bool {
|
||||
const __dynamic_map_full = proc(using h: __MapHeader) -> bool {
|
||||
return int(0.75 * f64(len(m.hashes))) <= m.entries.cap;
|
||||
}
|
||||
|
||||
|
||||
__dynamic_map_hash_equal :: proc(h: __MapHeader, a, b: __MapKey) -> bool {
|
||||
const __dynamic_map_hash_equal = proc(h: __MapHeader, a, b: __MapKey) -> bool {
|
||||
if a.hash == b.hash {
|
||||
if h.is_key_string {
|
||||
return a.str == b.str;
|
||||
@@ -696,13 +696,13 @@ __dynamic_map_hash_equal :: proc(h: __MapHeader, a, b: __MapKey) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
__dynamic_map_find :: proc(using h: __MapHeader, key: __MapKey) -> __MapFindResult {
|
||||
fr := __MapFindResult{-1, -1, -1};
|
||||
const __dynamic_map_find = proc(using h: __MapHeader, key: __MapKey) -> __MapFindResult {
|
||||
var fr = __MapFindResult{-1, -1, -1};
|
||||
if len(m.hashes) > 0 {
|
||||
fr.hash_index = int(key.hash % u128(len(m.hashes)));
|
||||
fr.entry_index = m.hashes[fr.hash_index];
|
||||
for fr.entry_index >= 0 {
|
||||
entry := __dynamic_map_get_entry(h, fr.entry_index);
|
||||
var entry = __dynamic_map_get_entry(h, fr.entry_index);
|
||||
if __dynamic_map_hash_equal(h, entry.key, key) {
|
||||
return fr;
|
||||
}
|
||||
@@ -713,11 +713,11 @@ __dynamic_map_find :: proc(using h: __MapHeader, key: __MapKey) -> __MapFindResu
|
||||
return fr;
|
||||
}
|
||||
|
||||
__dynamic_map_add_entry :: proc(using h: __MapHeader, key: __MapKey) -> int {
|
||||
prev := m.entries.len;
|
||||
c := __dynamic_array_append_nothing(&m.entries, entry_size, entry_align);
|
||||
const __dynamic_map_add_entry = proc(using h: __MapHeader, key: __MapKey) -> int {
|
||||
var prev = m.entries.len;
|
||||
var c = __dynamic_array_append_nothing(&m.entries, entry_size, entry_align);
|
||||
if c != prev {
|
||||
end := __dynamic_map_get_entry(h, c-1);
|
||||
var end = __dynamic_map_get_entry(h, c-1);
|
||||
end.key = key;
|
||||
end.next = -1;
|
||||
}
|
||||
@@ -725,19 +725,19 @@ __dynamic_map_add_entry :: proc(using h: __MapHeader, key: __MapKey) -> int {
|
||||
}
|
||||
|
||||
|
||||
__dynamic_map_delete :: proc(using h: __MapHeader, key: __MapKey) {
|
||||
fr := __dynamic_map_find(h, key);
|
||||
const __dynamic_map_delete = proc(using h: __MapHeader, key: __MapKey) {
|
||||
var fr = __dynamic_map_find(h, key);
|
||||
if fr.entry_index >= 0 {
|
||||
__dynamic_map_erase(h, fr);
|
||||
}
|
||||
}
|
||||
|
||||
__dynamic_map_get_entry :: proc(using h: __MapHeader, index: int) -> ^__MapEntryHeader {
|
||||
data := ^u8(m.entries.data) + index*entry_size;
|
||||
const __dynamic_map_get_entry = proc(using h: __MapHeader, index: int) -> ^__MapEntryHeader {
|
||||
var data = ^u8(m.entries.data) + index*entry_size;
|
||||
return ^__MapEntryHeader(data);
|
||||
}
|
||||
|
||||
__dynamic_map_erase :: proc(using h: __MapHeader, fr: __MapFindResult) {
|
||||
const __dynamic_map_erase = proc(using h: __MapHeader, fr: __MapFindResult) {
|
||||
if fr.entry_prev < 0 {
|
||||
m.hashes[fr.hash_index] = __dynamic_map_get_entry(h, fr.entry_index).next;
|
||||
} else {
|
||||
@@ -748,7 +748,7 @@ __dynamic_map_erase :: proc(using h: __MapHeader, fr: __MapFindResult) {
|
||||
m.entries.len--;
|
||||
}
|
||||
__mem_copy(__dynamic_map_get_entry(h, fr.entry_index), __dynamic_map_get_entry(h, m.entries.len-1), entry_size);
|
||||
last := __dynamic_map_find(h, __dynamic_map_get_entry(h, fr.entry_index).key);
|
||||
var last = __dynamic_map_find(h, __dynamic_map_get_entry(h, fr.entry_index).key);
|
||||
if last.entry_prev >= 0 {
|
||||
__dynamic_map_get_entry(h, last.entry_prev).next = fr.entry_index;
|
||||
} else {
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
#shared_global_scope;
|
||||
|
||||
__u128_mod :: proc(a, b: u128) -> u128 #cc_odin #link_name "__umodti3" {
|
||||
r: u128;
|
||||
const __u128_mod = proc(a, b: u128) -> u128 #cc_odin #link_name "__umodti3" {
|
||||
var r: u128;
|
||||
__u128_quo_mod(a, b, &r);
|
||||
return r;
|
||||
}
|
||||
|
||||
__u128_quo :: proc(a, b: u128) -> u128 #cc_odin #link_name "__udivti3" {
|
||||
const __u128_quo = proc(a, b: u128) -> u128 #cc_odin #link_name "__udivti3" {
|
||||
return __u128_quo_mod(a, b, nil);
|
||||
}
|
||||
|
||||
__i128_mod :: proc(a, b: i128) -> i128 #cc_odin #link_name "__modti3" {
|
||||
r: i128;
|
||||
const __i128_mod = proc(a, b: i128) -> i128 #cc_odin #link_name "__modti3" {
|
||||
var r: i128;
|
||||
__i128_quo_mod(a, b, &r);
|
||||
return r;
|
||||
}
|
||||
|
||||
__i128_quo :: proc(a, b: i128) -> i128 #cc_odin #link_name "__divti3" {
|
||||
const __i128_quo = proc(a, b: i128) -> i128 #cc_odin #link_name "__divti3" {
|
||||
return __i128_quo_mod(a, b, nil);
|
||||
}
|
||||
|
||||
__i128_quo_mod :: proc(a, b: i128, rem: ^i128) -> (quo: i128) #cc_odin #link_name "__divmodti4" {
|
||||
s: i128;
|
||||
const __i128_quo_mod = proc(a, b: i128, rem: ^i128) -> (quo: i128) #cc_odin #link_name "__divmodti4" {
|
||||
var s: i128;
|
||||
s = b >> 127;
|
||||
b = (b~s) - s;
|
||||
s = a >> 127;
|
||||
b = (a~s) - s;
|
||||
|
||||
uquo: u128;
|
||||
urem := __u128_quo_mod(transmute(u128, a), transmute(u128, b), &uquo);
|
||||
iquo := transmute(i128, uquo);
|
||||
irem := transmute(i128, urem);
|
||||
var uquo: u128;
|
||||
var urem = __u128_quo_mod(transmute(u128, a), transmute(u128, b), &uquo);
|
||||
var iquo = transmute(i128, uquo);
|
||||
var irem = transmute(i128, urem);
|
||||
|
||||
iquo = (iquo~s) - s;
|
||||
irem = (irem~s) - s;
|
||||
@@ -39,15 +39,15 @@ __i128_quo_mod :: proc(a, b: i128, rem: ^i128) -> (quo: i128) #cc_odin #link_nam
|
||||
}
|
||||
|
||||
|
||||
__u128_quo_mod :: proc(a, b: u128, rem: ^u128) -> (quo: u128) #cc_odin #link_name "__udivmodti4" {
|
||||
alo, ahi := u64(a), u64(a>>64);
|
||||
blo, bhi := u64(b), u64(b>>64);
|
||||
const __u128_quo_mod = proc(a, b: u128, rem: ^u128) -> (quo: u128) #cc_odin #link_name "__udivmodti4" {
|
||||
var alo, ahi = u64(a), u64(a>>64);
|
||||
var blo, bhi = u64(b), u64(b>>64);
|
||||
if b == 0 {
|
||||
if rem != nil { rem^ = 0; }
|
||||
return u128(alo/blo);
|
||||
}
|
||||
|
||||
r, d, x, q: u128 = a, b, 1, 0;
|
||||
var r, d, x, q: u128 = a, b, 1, 0;
|
||||
|
||||
for r >= d && (d>>127)&1 == 0 {
|
||||
x <<= 1;
|
||||
@@ -68,10 +68,10 @@ __u128_quo_mod :: proc(a, b: u128, rem: ^u128) -> (quo: u128) #cc_odin #link_nam
|
||||
}
|
||||
|
||||
/*
|
||||
__f16_to_f32 :: proc(f: f16) -> f32 #cc_odin #no_inline #link_name "__gnu_h2f_ieee" {
|
||||
const __f16_to_f32 = proc(f: f16) -> f32 #cc_odin #no_inline #link_name "__gnu_h2f_ieee" {
|
||||
when true {
|
||||
// Source: https://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
|
||||
FP32 :: raw_union {u: u32, f: f32};
|
||||
const FP32 = raw_union {u: u32, f: f32};
|
||||
|
||||
magic, was_infnan: FP32;
|
||||
magic.u = (254-15) << 23;
|
||||
@@ -92,19 +92,19 @@ __f16_to_f32 :: proc(f: f16) -> f32 #cc_odin #no_inline #link_name "__gnu_h2f_ie
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
__f32_to_f16 :: proc(f_: f32) -> f16 #cc_odin #no_inline #link_name "__gnu_f2h_ieee" {
|
||||
const __f32_to_f16 = proc(f_: f32) -> f16 #cc_odin #no_inline #link_name "__gnu_f2h_ieee" {
|
||||
when false {
|
||||
// Source: https://gist.github.com/rygorous/2156668
|
||||
FP16 :: raw_union {u: u16, f: f16};
|
||||
FP32 :: raw_union {u: u32, f: f32};
|
||||
const FP16 = raw_union {u: u16, f: f16};
|
||||
const FP32 = raw_union {u: u32, f: f32};
|
||||
|
||||
f32infty, f16infty, magic: FP32;
|
||||
f32infty.u = 255<<23;
|
||||
f16infty.u = 31<<23;
|
||||
magic.u = 15<<23;
|
||||
|
||||
sign_mask :: u32(0x80000000);
|
||||
round_mask :: ~u32(0x0fff);
|
||||
const sign_mask = u32(0x80000000);
|
||||
const round_mask = ~u32(0x0fff);
|
||||
|
||||
f := transmute(FP32, f_);
|
||||
|
||||
@@ -182,11 +182,11 @@ __f32_to_f16 :: proc(f_: f32) -> f16 #cc_odin #no_inline #link_name "__gnu_f2h_i
|
||||
}
|
||||
}
|
||||
|
||||
__f64_to_f16 :: proc(f: f64) -> f16 #cc_odin #no_inline #link_name "__truncdfhf2" {
|
||||
const __f64_to_f16 = proc(f: f64) -> f16 #cc_odin #no_inline #link_name "__truncdfhf2" {
|
||||
return __f32_to_f16(f32(f));
|
||||
}
|
||||
|
||||
__f16_to_f64 :: proc(f: f16) -> f64 #cc_odin #no_inline {
|
||||
const __f16_to_f64 = proc(f: f16) -> f64 #cc_odin #no_inline {
|
||||
return f64(__f16_to_f32(f));
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -2,40 +2,40 @@
|
||||
// Inline vs external file?
|
||||
|
||||
#import win32 "sys/windows.odin" when ODIN_OS == "windows";
|
||||
_ := compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version
|
||||
var _ = compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version
|
||||
|
||||
|
||||
yield_thread :: proc() { win32.mm_pause(); }
|
||||
mfence :: proc() { win32.read_write_barrier(); }
|
||||
sfence :: proc() { win32.write_barrier(); }
|
||||
lfence :: proc() { win32.read_barrier(); }
|
||||
const yield_thread = proc() { win32.mm_pause(); }
|
||||
const mfence = proc() { win32.read_write_barrier(); }
|
||||
const sfence = proc() { win32.write_barrier(); }
|
||||
const lfence = proc() { win32.read_barrier(); }
|
||||
|
||||
|
||||
load :: proc(a: ^i32) -> i32 {
|
||||
const load = proc(a: ^i32) -> i32 {
|
||||
return a^;
|
||||
}
|
||||
store :: proc(a: ^i32, value: i32) {
|
||||
const store = proc(a: ^i32, value: i32) {
|
||||
a^ = value;
|
||||
}
|
||||
compare_exchange :: proc(a: ^i32, expected, desired: i32) -> i32 {
|
||||
const compare_exchange = proc(a: ^i32, expected, desired: i32) -> i32 {
|
||||
return win32.interlocked_compare_exchange(a, desired, expected);
|
||||
}
|
||||
exchanged :: proc(a: ^i32, desired: i32) -> i32 {
|
||||
const exchanged = proc(a: ^i32, desired: i32) -> i32 {
|
||||
return win32.interlocked_exchange(a, desired);
|
||||
}
|
||||
fetch_add :: proc(a: ^i32, operand: i32) -> i32 {
|
||||
const fetch_add = proc(a: ^i32, operand: i32) -> i32 {
|
||||
return win32.interlocked_exchange_add(a, operand);
|
||||
|
||||
}
|
||||
fetch_and :: proc(a: ^i32, operand: i32) -> i32 {
|
||||
const fetch_and = proc(a: ^i32, operand: i32) -> i32 {
|
||||
return win32.interlocked_and(a, operand);
|
||||
}
|
||||
fetch_or :: proc(a: ^i32, operand: i32) -> i32 {
|
||||
const fetch_or = proc(a: ^i32, operand: i32) -> i32 {
|
||||
return win32.interlocked_or(a, operand);
|
||||
}
|
||||
spin_lock :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
||||
old_value := compare_exchange(a, 1, 0);
|
||||
counter := 0;
|
||||
const spin_lock = proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
||||
var old_value = compare_exchange(a, 1, 0);
|
||||
var counter = 0;
|
||||
for old_value != 0 && (time_out < 0 || counter < time_out) {
|
||||
counter++;
|
||||
yield_thread();
|
||||
@@ -44,42 +44,42 @@ spin_lock :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1
|
||||
}
|
||||
return old_value == 0;
|
||||
}
|
||||
spin_unlock :: proc(a: ^i32) {
|
||||
const spin_unlock = proc(a: ^i32) {
|
||||
store(a, 0);
|
||||
mfence();
|
||||
}
|
||||
try_acquire_lock :: proc(a: ^i32) -> bool {
|
||||
const try_acquire_lock = proc(a: ^i32) -> bool {
|
||||
yield_thread();
|
||||
old_value := compare_exchange(a, 1, 0);
|
||||
var old_value = compare_exchange(a, 1, 0);
|
||||
mfence();
|
||||
return old_value == 0;
|
||||
}
|
||||
|
||||
|
||||
load :: proc(a: ^i64) -> i64 {
|
||||
const load = proc(a: ^i64) -> i64 {
|
||||
return a^;
|
||||
}
|
||||
store :: proc(a: ^i64, value: i64) {
|
||||
const store = proc(a: ^i64, value: i64) {
|
||||
a^ = value;
|
||||
}
|
||||
compare_exchange :: proc(a: ^i64, expected, desired: i64) -> i64 {
|
||||
const compare_exchange = proc(a: ^i64, expected, desired: i64) -> i64 {
|
||||
return win32.interlocked_compare_exchange64(a, desired, expected);
|
||||
}
|
||||
exchanged :: proc(a: ^i64, desired: i64) -> i64 {
|
||||
const exchanged = proc(a: ^i64, desired: i64) -> i64 {
|
||||
return win32.interlocked_exchange64(a, desired);
|
||||
}
|
||||
fetch_add :: proc(a: ^i64, operand: i64) -> i64 {
|
||||
const fetch_add = proc(a: ^i64, operand: i64) -> i64 {
|
||||
return win32.interlocked_exchange_add64(a, operand);
|
||||
}
|
||||
fetch_and :: proc(a: ^i64, operand: i64) -> i64 {
|
||||
const fetch_and = proc(a: ^i64, operand: i64) -> i64 {
|
||||
return win32.interlocked_and64(a, operand);
|
||||
}
|
||||
fetch_or :: proc(a: ^i64, operand: i64) -> i64 {
|
||||
const fetch_or = proc(a: ^i64, operand: i64) -> i64 {
|
||||
return win32.interlocked_or64(a, operand);
|
||||
}
|
||||
spin_lock :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
||||
old_value := compare_exchange(a, 1, 0);
|
||||
counter := 0;
|
||||
const spin_lock = proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
||||
var old_value = compare_exchange(a, 1, 0);
|
||||
var counter = 0;
|
||||
for old_value != 0 && (time_out < 0 || counter < time_out) {
|
||||
counter++;
|
||||
yield_thread();
|
||||
@@ -88,13 +88,13 @@ spin_lock :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1
|
||||
}
|
||||
return old_value == 0;
|
||||
}
|
||||
spin_unlock :: proc(a: ^i64) {
|
||||
const spin_unlock = proc(a: ^i64) {
|
||||
store(a, 0);
|
||||
mfence();
|
||||
}
|
||||
try_acquire_lock :: proc(a: ^i64) -> bool {
|
||||
const try_acquire_lock = proc(a: ^i64) -> bool {
|
||||
yield_thread();
|
||||
old_value := compare_exchange(a, 1, 0);
|
||||
var old_value = compare_exchange(a, 1, 0);
|
||||
mfence();
|
||||
return old_value == 0;
|
||||
}
|
||||
|
||||
444
core/bits.odin
444
core/bits.odin
@@ -1,286 +1,286 @@
|
||||
U8_MIN :: u8(0);
|
||||
U16_MIN :: u16(0);
|
||||
U32_MIN :: u32(0);
|
||||
U64_MIN :: u64(0);
|
||||
U128_MIN :: u128(0);
|
||||
const U8_MIN = u8(0);
|
||||
const U16_MIN = u16(0);
|
||||
const U32_MIN = u32(0);
|
||||
const U64_MIN = u64(0);
|
||||
const U128_MIN = u128(0);
|
||||
|
||||
I8_MIN :: i8(-0x80);
|
||||
I16_MIN :: i16(-0x8000);
|
||||
I32_MIN :: i32(-0x8000_0000);
|
||||
I64_MIN :: i64(-0x8000_0000_0000_0000);
|
||||
I128_MIN :: i128(-0x8000_0000_0000_0000_0000_0000_0000_0000);
|
||||
const I8_MIN = i8(-0x80);
|
||||
const I16_MIN = i16(-0x8000);
|
||||
const I32_MIN = i32(-0x8000_0000);
|
||||
const I64_MIN = i64(-0x8000_0000_0000_0000);
|
||||
const I128_MIN = i128(-0x8000_0000_0000_0000_0000_0000_0000_0000);
|
||||
|
||||
U8_MAX :: ~u8(0);
|
||||
U16_MAX :: ~u16(0);
|
||||
U32_MAX :: ~u32(0);
|
||||
U64_MAX :: ~u64(0);
|
||||
U128_MAX :: ~u128(0);
|
||||
const U8_MAX = ~u8(0);
|
||||
const U16_MAX = ~u16(0);
|
||||
const U32_MAX = ~u32(0);
|
||||
const U64_MAX = ~u64(0);
|
||||
const U128_MAX = ~u128(0);
|
||||
|
||||
I8_MAX :: i8(0x7f);
|
||||
I16_MAX :: i16(0x7fff);
|
||||
I32_MAX :: i32(0x7fff_ffff);
|
||||
I64_MAX :: i64(0x7fff_ffff_ffff_ffff);
|
||||
I128_MAX :: i128(0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ffff);
|
||||
const I8_MAX = i8(0x7f);
|
||||
const I16_MAX = i16(0x7fff);
|
||||
const I32_MAX = i32(0x7fff_ffff);
|
||||
const I64_MAX = i64(0x7fff_ffff_ffff_ffff);
|
||||
const I128_MAX = i128(0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ffff);
|
||||
|
||||
|
||||
count_ones :: proc(i: u8) -> u8 { __llvm_ctpop :: proc(u8) -> u8 #foreign __llvm_core "llvm.ctpop.i8"; return __llvm_ctpop(i); }
|
||||
count_ones :: proc(i: i8) -> i8 { __llvm_ctpop :: proc(i8) -> i8 #foreign __llvm_core "llvm.ctpop.i8"; return __llvm_ctpop(i); }
|
||||
count_ones :: proc(i: u16) -> u16 { __llvm_ctpop :: proc(u16) -> u16 #foreign __llvm_core "llvm.ctpop.i16"; return __llvm_ctpop(i); }
|
||||
count_ones :: proc(i: i16) -> i16 { __llvm_ctpop :: proc(i16) -> i16 #foreign __llvm_core "llvm.ctpop.i16"; return __llvm_ctpop(i); }
|
||||
count_ones :: proc(i: u32) -> u32 { __llvm_ctpop :: proc(u32) -> u32 #foreign __llvm_core "llvm.ctpop.i32"; return __llvm_ctpop(i); }
|
||||
count_ones :: proc(i: i32) -> i32 { __llvm_ctpop :: proc(i32) -> i32 #foreign __llvm_core "llvm.ctpop.i32"; return __llvm_ctpop(i); }
|
||||
count_ones :: proc(i: u64) -> u64 { __llvm_ctpop :: proc(u64) -> u64 #foreign __llvm_core "llvm.ctpop.i64"; return __llvm_ctpop(i); }
|
||||
count_ones :: proc(i: i64) -> i64 { __llvm_ctpop :: proc(i64) -> i64 #foreign __llvm_core "llvm.ctpop.i64"; return __llvm_ctpop(i); }
|
||||
count_ones :: proc(i: u128) -> u128 { __llvm_ctpop :: proc(u128) -> u128 #foreign __llvm_core "llvm.ctpop.i128";return __llvm_ctpop(i); }
|
||||
count_ones :: proc(i: i128) -> i128 { __llvm_ctpop :: proc(i128) -> i128 #foreign __llvm_core "llvm.ctpop.i128";return __llvm_ctpop(i); }
|
||||
count_ones :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(count_ones(u32(i))); } else { return uint(count_ones(u64(i))); } }
|
||||
count_ones :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(count_ones(i32(i))); } else { return int(count_ones(i64(i))); } }
|
||||
const count_ones = proc(i: u8) -> u8 { const __llvm_ctpop = proc(u8) -> u8 #foreign __llvm_core "llvm.ctpop.i8"; return __llvm_ctpop(i); }
|
||||
const count_ones = proc(i: i8) -> i8 { const __llvm_ctpop = proc(i8) -> i8 #foreign __llvm_core "llvm.ctpop.i8"; return __llvm_ctpop(i); }
|
||||
const count_ones = proc(i: u16) -> u16 { const __llvm_ctpop = proc(u16) -> u16 #foreign __llvm_core "llvm.ctpop.i16"; return __llvm_ctpop(i); }
|
||||
const count_ones = proc(i: i16) -> i16 { const __llvm_ctpop = proc(i16) -> i16 #foreign __llvm_core "llvm.ctpop.i16"; return __llvm_ctpop(i); }
|
||||
const count_ones = proc(i: u32) -> u32 { const __llvm_ctpop = proc(u32) -> u32 #foreign __llvm_core "llvm.ctpop.i32"; return __llvm_ctpop(i); }
|
||||
const count_ones = proc(i: i32) -> i32 { const __llvm_ctpop = proc(i32) -> i32 #foreign __llvm_core "llvm.ctpop.i32"; return __llvm_ctpop(i); }
|
||||
const count_ones = proc(i: u64) -> u64 { const __llvm_ctpop = proc(u64) -> u64 #foreign __llvm_core "llvm.ctpop.i64"; return __llvm_ctpop(i); }
|
||||
const count_ones = proc(i: i64) -> i64 { const __llvm_ctpop = proc(i64) -> i64 #foreign __llvm_core "llvm.ctpop.i64"; return __llvm_ctpop(i); }
|
||||
const count_ones = proc(i: u128) -> u128 { const __llvm_ctpop = proc(u128) -> u128 #foreign __llvm_core "llvm.ctpop.i128";return __llvm_ctpop(i); }
|
||||
const count_ones = proc(i: i128) -> i128 { const __llvm_ctpop = proc(i128) -> i128 #foreign __llvm_core "llvm.ctpop.i128";return __llvm_ctpop(i); }
|
||||
const count_ones = proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(count_ones(u32(i))); } else { return uint(count_ones(u64(i))); } }
|
||||
const count_ones = proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(count_ones(i32(i))); } else { return int(count_ones(i64(i))); } }
|
||||
|
||||
count_zeros :: proc(i: u8) -> u8 { return 8 - count_ones(i); }
|
||||
count_zeros :: proc(i: i8) -> i8 { return 8 - count_ones(i); }
|
||||
count_zeros :: proc(i: u16) -> u16 { return 16 - count_ones(i); }
|
||||
count_zeros :: proc(i: i16) -> i16 { return 16 - count_ones(i); }
|
||||
count_zeros :: proc(i: u32) -> u32 { return 32 - count_ones(i); }
|
||||
count_zeros :: proc(i: i32) -> i32 { return 32 - count_ones(i); }
|
||||
count_zeros :: proc(i: u64) -> u64 { return 64 - count_ones(i); }
|
||||
count_zeros :: proc(i: i64) -> i64 { return 64 - count_ones(i); }
|
||||
count_zeros :: proc(i: u128) -> u128 { return 128 - count_ones(i); }
|
||||
count_zeros :: proc(i: i128) -> i128 { return 128 - count_ones(i); }
|
||||
count_zeros :: proc(i: uint) -> uint { return 8*size_of(uint) - count_ones(i); }
|
||||
count_zeros :: proc(i: int) -> int { return 8*size_of(int) - count_ones(i); }
|
||||
const count_zeros = proc(i: u8) -> u8 { return 8 - count_ones(i); }
|
||||
const count_zeros = proc(i: i8) -> i8 { return 8 - count_ones(i); }
|
||||
const count_zeros = proc(i: u16) -> u16 { return 16 - count_ones(i); }
|
||||
const count_zeros = proc(i: i16) -> i16 { return 16 - count_ones(i); }
|
||||
const count_zeros = proc(i: u32) -> u32 { return 32 - count_ones(i); }
|
||||
const count_zeros = proc(i: i32) -> i32 { return 32 - count_ones(i); }
|
||||
const count_zeros = proc(i: u64) -> u64 { return 64 - count_ones(i); }
|
||||
const count_zeros = proc(i: i64) -> i64 { return 64 - count_ones(i); }
|
||||
const count_zeros = proc(i: u128) -> u128 { return 128 - count_ones(i); }
|
||||
const count_zeros = proc(i: i128) -> i128 { return 128 - count_ones(i); }
|
||||
const count_zeros = proc(i: uint) -> uint { return 8*size_of(uint) - count_ones(i); }
|
||||
const count_zeros = proc(i: int) -> int { return 8*size_of(int) - count_ones(i); }
|
||||
|
||||
|
||||
rotate_left :: proc(i: u8, s: uint) -> u8 { return (i << s)|(i >> (8*size_of(u8) - s)); }
|
||||
rotate_left :: proc(i: i8, s: uint) -> i8 { return (i << s)|(i >> (8*size_of(i8) - s)); }
|
||||
rotate_left :: proc(i: u16, s: uint) -> u16 { return (i << s)|(i >> (8*size_of(u16) - s)); }
|
||||
rotate_left :: proc(i: i16, s: uint) -> i16 { return (i << s)|(i >> (8*size_of(i16) - s)); }
|
||||
rotate_left :: proc(i: u32, s: uint) -> u32 { return (i << s)|(i >> (8*size_of(u32) - s)); }
|
||||
rotate_left :: proc(i: i32, s: uint) -> i32 { return (i << s)|(i >> (8*size_of(i32) - s)); }
|
||||
rotate_left :: proc(i: u64, s: uint) -> u64 { return (i << s)|(i >> (8*size_of(u64) - s)); }
|
||||
rotate_left :: proc(i: i64, s: uint) -> i64 { return (i << s)|(i >> (8*size_of(i64) - s)); }
|
||||
rotate_left :: proc(i: u128, s: uint) -> u128 { return (i << s)|(i >> (8*size_of(u128) - s)); }
|
||||
rotate_left :: proc(i: i128, s: uint) -> i128 { return (i << s)|(i >> (8*size_of(i128) - s)); }
|
||||
rotate_left :: proc(i: uint, s: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(rotate_left(u32(i), s)); } else { return uint(rotate_left(u64(i), s)); } }
|
||||
rotate_left :: proc(i: int, s: uint) -> int { when size_of(int) == size_of(i32) { return int(rotate_left(i32(i), s)); } else { return int(rotate_left(i64(i), s)); } }
|
||||
const rotate_left = proc(i: u8, s: uint) -> u8 { return (i << s)|(i >> (8*size_of(u8) - s)); }
|
||||
const rotate_left = proc(i: i8, s: uint) -> i8 { return (i << s)|(i >> (8*size_of(i8) - s)); }
|
||||
const rotate_left = proc(i: u16, s: uint) -> u16 { return (i << s)|(i >> (8*size_of(u16) - s)); }
|
||||
const rotate_left = proc(i: i16, s: uint) -> i16 { return (i << s)|(i >> (8*size_of(i16) - s)); }
|
||||
const rotate_left = proc(i: u32, s: uint) -> u32 { return (i << s)|(i >> (8*size_of(u32) - s)); }
|
||||
const rotate_left = proc(i: i32, s: uint) -> i32 { return (i << s)|(i >> (8*size_of(i32) - s)); }
|
||||
const rotate_left = proc(i: u64, s: uint) -> u64 { return (i << s)|(i >> (8*size_of(u64) - s)); }
|
||||
const rotate_left = proc(i: i64, s: uint) -> i64 { return (i << s)|(i >> (8*size_of(i64) - s)); }
|
||||
const rotate_left = proc(i: u128, s: uint) -> u128 { return (i << s)|(i >> (8*size_of(u128) - s)); }
|
||||
const rotate_left = proc(i: i128, s: uint) -> i128 { return (i << s)|(i >> (8*size_of(i128) - s)); }
|
||||
const rotate_left = proc(i: uint, s: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(rotate_left(u32(i), s)); } else { return uint(rotate_left(u64(i), s)); } }
|
||||
const rotate_left = proc(i: int, s: uint) -> int { when size_of(int) == size_of(i32) { return int(rotate_left(i32(i), s)); } else { return int(rotate_left(i64(i), s)); } }
|
||||
|
||||
|
||||
rotate_right :: proc(i: u8, s: uint) -> u8 { return (i >> s)|(i << (8*size_of(u8) - s)); }
|
||||
rotate_right :: proc(i: i8, s: uint) -> i8 { return (i >> s)|(i << (8*size_of(i8) - s)); }
|
||||
rotate_right :: proc(i: u16, s: uint) -> u16 { return (i >> s)|(i << (8*size_of(u16) - s)); }
|
||||
rotate_right :: proc(i: i16, s: uint) -> i16 { return (i >> s)|(i << (8*size_of(i16) - s)); }
|
||||
rotate_right :: proc(i: u32, s: uint) -> u32 { return (i >> s)|(i << (8*size_of(u32) - s)); }
|
||||
rotate_right :: proc(i: i32, s: uint) -> i32 { return (i >> s)|(i << (8*size_of(i32) - s)); }
|
||||
rotate_right :: proc(i: u64, s: uint) -> u64 { return (i >> s)|(i << (8*size_of(u64) - s)); }
|
||||
rotate_right :: proc(i: i64, s: uint) -> i64 { return (i >> s)|(i << (8*size_of(i64) - s)); }
|
||||
rotate_right :: proc(i: u128, s: uint) -> u128 { return (i >> s)|(i << (8*size_of(u128) - s)); }
|
||||
rotate_right :: proc(i: i128, s: uint) -> i128 { return (i >> s)|(i << (8*size_of(i128) - s)); }
|
||||
rotate_right :: proc(i: uint, s: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(rotate_right(u32(i), s)); } else { return uint(rotate_right(u64(i), s)); } }
|
||||
rotate_right :: proc(i: int, s: uint) -> int { when size_of(int) == size_of(i32) { return int(rotate_right(i32(i), s)); } else { return int(rotate_right(i64(i), s)); } }
|
||||
const rotate_right = proc(i: u8, s: uint) -> u8 { return (i >> s)|(i << (8*size_of(u8) - s)); }
|
||||
const rotate_right = proc(i: i8, s: uint) -> i8 { return (i >> s)|(i << (8*size_of(i8) - s)); }
|
||||
const rotate_right = proc(i: u16, s: uint) -> u16 { return (i >> s)|(i << (8*size_of(u16) - s)); }
|
||||
const rotate_right = proc(i: i16, s: uint) -> i16 { return (i >> s)|(i << (8*size_of(i16) - s)); }
|
||||
const rotate_right = proc(i: u32, s: uint) -> u32 { return (i >> s)|(i << (8*size_of(u32) - s)); }
|
||||
const rotate_right = proc(i: i32, s: uint) -> i32 { return (i >> s)|(i << (8*size_of(i32) - s)); }
|
||||
const rotate_right = proc(i: u64, s: uint) -> u64 { return (i >> s)|(i << (8*size_of(u64) - s)); }
|
||||
const rotate_right = proc(i: i64, s: uint) -> i64 { return (i >> s)|(i << (8*size_of(i64) - s)); }
|
||||
const rotate_right = proc(i: u128, s: uint) -> u128 { return (i >> s)|(i << (8*size_of(u128) - s)); }
|
||||
const rotate_right = proc(i: i128, s: uint) -> i128 { return (i >> s)|(i << (8*size_of(i128) - s)); }
|
||||
const rotate_right = proc(i: uint, s: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(rotate_right(u32(i), s)); } else { return uint(rotate_right(u64(i), s)); } }
|
||||
const rotate_right = proc(i: int, s: uint) -> int { when size_of(int) == size_of(i32) { return int(rotate_right(i32(i), s)); } else { return int(rotate_right(i64(i), s)); } }
|
||||
|
||||
|
||||
leading_zeros :: proc(i: u8) -> u8 { __llvm_ctlz :: proc(u8, bool) -> u8 #foreign __llvm_core "llvm.ctlz.i8"; return __llvm_ctlz(i, false); }
|
||||
leading_zeros :: proc(i: i8) -> i8 { __llvm_ctlz :: proc(i8, bool) -> i8 #foreign __llvm_core "llvm.ctlz.i8"; return __llvm_ctlz(i, false); }
|
||||
leading_zeros :: proc(i: u16) -> u16 { __llvm_ctlz :: proc(u16, bool) -> u16 #foreign __llvm_core "llvm.ctlz.i16"; return __llvm_ctlz(i, false); }
|
||||
leading_zeros :: proc(i: i16) -> i16 { __llvm_ctlz :: proc(i16, bool) -> i16 #foreign __llvm_core "llvm.ctlz.i16"; return __llvm_ctlz(i, false); }
|
||||
leading_zeros :: proc(i: u32) -> u32 { __llvm_ctlz :: proc(u32, bool) -> u32 #foreign __llvm_core "llvm.ctlz.i32"; return __llvm_ctlz(i, false); }
|
||||
leading_zeros :: proc(i: i32) -> i32 { __llvm_ctlz :: proc(i32, bool) -> i32 #foreign __llvm_core "llvm.ctlz.i32"; return __llvm_ctlz(i, false); }
|
||||
leading_zeros :: proc(i: u64) -> u64 { __llvm_ctlz :: proc(u64, bool) -> u64 #foreign __llvm_core "llvm.ctlz.i64"; return __llvm_ctlz(i, false); }
|
||||
leading_zeros :: proc(i: i64) -> i64 { __llvm_ctlz :: proc(i64, bool) -> i64 #foreign __llvm_core "llvm.ctlz.i64"; return __llvm_ctlz(i, false); }
|
||||
leading_zeros :: proc(i: u128) -> u128 { __llvm_ctlz :: proc(u128, bool) -> u128 #foreign __llvm_core "llvm.ctlz.i128";return __llvm_ctlz(i, false); }
|
||||
leading_zeros :: proc(i: i128) -> i128 { __llvm_ctlz :: proc(i128, bool) -> i128 #foreign __llvm_core "llvm.ctlz.i128";return __llvm_ctlz(i, false); }
|
||||
leading_zeros :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(leading_zeros(u32(i))); } else { return uint(leading_zeros(u64(i))); } }
|
||||
leading_zeros :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(leading_zeros(i32(i))); } else { return int(leading_zeros(i64(i))); } }
|
||||
const leading_zeros = proc(i: u8) -> u8 { const __llvm_ctlz = proc(u8, bool) -> u8 #foreign __llvm_core "llvm.ctlz.i8"; return __llvm_ctlz(i, false); }
|
||||
const leading_zeros = proc(i: i8) -> i8 { const __llvm_ctlz = proc(i8, bool) -> i8 #foreign __llvm_core "llvm.ctlz.i8"; return __llvm_ctlz(i, false); }
|
||||
const leading_zeros = proc(i: u16) -> u16 { const __llvm_ctlz = proc(u16, bool) -> u16 #foreign __llvm_core "llvm.ctlz.i16"; return __llvm_ctlz(i, false); }
|
||||
const leading_zeros = proc(i: i16) -> i16 { const __llvm_ctlz = proc(i16, bool) -> i16 #foreign __llvm_core "llvm.ctlz.i16"; return __llvm_ctlz(i, false); }
|
||||
const leading_zeros = proc(i: u32) -> u32 { const __llvm_ctlz = proc(u32, bool) -> u32 #foreign __llvm_core "llvm.ctlz.i32"; return __llvm_ctlz(i, false); }
|
||||
const leading_zeros = proc(i: i32) -> i32 { const __llvm_ctlz = proc(i32, bool) -> i32 #foreign __llvm_core "llvm.ctlz.i32"; return __llvm_ctlz(i, false); }
|
||||
const leading_zeros = proc(i: u64) -> u64 { const __llvm_ctlz = proc(u64, bool) -> u64 #foreign __llvm_core "llvm.ctlz.i64"; return __llvm_ctlz(i, false); }
|
||||
const leading_zeros = proc(i: i64) -> i64 { const __llvm_ctlz = proc(i64, bool) -> i64 #foreign __llvm_core "llvm.ctlz.i64"; return __llvm_ctlz(i, false); }
|
||||
const leading_zeros = proc(i: u128) -> u128 { const __llvm_ctlz = proc(u128, bool) -> u128 #foreign __llvm_core "llvm.ctlz.i128";return __llvm_ctlz(i, false); }
|
||||
const leading_zeros = proc(i: i128) -> i128 { const __llvm_ctlz = proc(i128, bool) -> i128 #foreign __llvm_core "llvm.ctlz.i128";return __llvm_ctlz(i, false); }
|
||||
const leading_zeros = proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(leading_zeros(u32(i))); } else { return uint(leading_zeros(u64(i))); } }
|
||||
const leading_zeros = proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(leading_zeros(i32(i))); } else { return int(leading_zeros(i64(i))); } }
|
||||
|
||||
trailing_zeros :: proc(i: u8) -> u8 { __llvm_cttz :: proc(u8, bool) -> u8 #foreign __llvm_core "llvm.cttz.i8"; return __llvm_cttz(i, false); }
|
||||
trailing_zeros :: proc(i: i8) -> i8 { __llvm_cttz :: proc(i8, bool) -> i8 #foreign __llvm_core "llvm.cttz.i8"; return __llvm_cttz(i, false); }
|
||||
trailing_zeros :: proc(i: u16) -> u16 { __llvm_cttz :: proc(u16, bool) -> u16 #foreign __llvm_core "llvm.cttz.i16"; return __llvm_cttz(i, false); }
|
||||
trailing_zeros :: proc(i: i16) -> i16 { __llvm_cttz :: proc(i16, bool) -> i16 #foreign __llvm_core "llvm.cttz.i16"; return __llvm_cttz(i, false); }
|
||||
trailing_zeros :: proc(i: u32) -> u32 { __llvm_cttz :: proc(u32, bool) -> u32 #foreign __llvm_core "llvm.cttz.i32"; return __llvm_cttz(i, false); }
|
||||
trailing_zeros :: proc(i: i32) -> i32 { __llvm_cttz :: proc(i32, bool) -> i32 #foreign __llvm_core "llvm.cttz.i32"; return __llvm_cttz(i, false); }
|
||||
trailing_zeros :: proc(i: u64) -> u64 { __llvm_cttz :: proc(u64, bool) -> u64 #foreign __llvm_core "llvm.cttz.i64"; return __llvm_cttz(i, false); }
|
||||
trailing_zeros :: proc(i: i64) -> i64 { __llvm_cttz :: proc(i64, bool) -> i64 #foreign __llvm_core "llvm.cttz.i64"; return __llvm_cttz(i, false); }
|
||||
trailing_zeros :: proc(i: u128) -> u128 { __llvm_cttz :: proc(u128, bool) -> u128 #foreign __llvm_core "llvm.cttz.i128";return __llvm_cttz(i, false); }
|
||||
trailing_zeros :: proc(i: i128) -> i128 { __llvm_cttz :: proc(i128, bool) -> i128 #foreign __llvm_core "llvm.cttz.i128";return __llvm_cttz(i, false); }
|
||||
trailing_zeros :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(trailing_zeros(u32(i))); } else { return uint(trailing_zeros(u64(i))); } }
|
||||
trailing_zeros :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(trailing_zeros(i32(i))); } else { return int(trailing_zeros(i64(i))); } }
|
||||
const trailing_zeros = proc(i: u8) -> u8 { const __llvm_cttz = proc(u8, bool) -> u8 #foreign __llvm_core "llvm.cttz.i8"; return __llvm_cttz(i, false); }
|
||||
const trailing_zeros = proc(i: i8) -> i8 { const __llvm_cttz = proc(i8, bool) -> i8 #foreign __llvm_core "llvm.cttz.i8"; return __llvm_cttz(i, false); }
|
||||
const trailing_zeros = proc(i: u16) -> u16 { const __llvm_cttz = proc(u16, bool) -> u16 #foreign __llvm_core "llvm.cttz.i16"; return __llvm_cttz(i, false); }
|
||||
const trailing_zeros = proc(i: i16) -> i16 { const __llvm_cttz = proc(i16, bool) -> i16 #foreign __llvm_core "llvm.cttz.i16"; return __llvm_cttz(i, false); }
|
||||
const trailing_zeros = proc(i: u32) -> u32 { const __llvm_cttz = proc(u32, bool) -> u32 #foreign __llvm_core "llvm.cttz.i32"; return __llvm_cttz(i, false); }
|
||||
const trailing_zeros = proc(i: i32) -> i32 { const __llvm_cttz = proc(i32, bool) -> i32 #foreign __llvm_core "llvm.cttz.i32"; return __llvm_cttz(i, false); }
|
||||
const trailing_zeros = proc(i: u64) -> u64 { const __llvm_cttz = proc(u64, bool) -> u64 #foreign __llvm_core "llvm.cttz.i64"; return __llvm_cttz(i, false); }
|
||||
const trailing_zeros = proc(i: i64) -> i64 { const __llvm_cttz = proc(i64, bool) -> i64 #foreign __llvm_core "llvm.cttz.i64"; return __llvm_cttz(i, false); }
|
||||
const trailing_zeros = proc(i: u128) -> u128 { const __llvm_cttz = proc(u128, bool) -> u128 #foreign __llvm_core "llvm.cttz.i128";return __llvm_cttz(i, false); }
|
||||
const trailing_zeros = proc(i: i128) -> i128 { const __llvm_cttz = proc(i128, bool) -> i128 #foreign __llvm_core "llvm.cttz.i128";return __llvm_cttz(i, false); }
|
||||
const trailing_zeros = proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(trailing_zeros(u32(i))); } else { return uint(trailing_zeros(u64(i))); } }
|
||||
const trailing_zeros = proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(trailing_zeros(i32(i))); } else { return int(trailing_zeros(i64(i))); } }
|
||||
|
||||
|
||||
reverse_bits :: proc(i: u8) -> u8 { __llvm_bitreverse :: proc(u8) -> u8 #foreign __llvm_core "llvm.bitreverse.i8"; return __llvm_bitreverse(i); }
|
||||
reverse_bits :: proc(i: i8) -> i8 { __llvm_bitreverse :: proc(i8) -> i8 #foreign __llvm_core "llvm.bitreverse.i8"; return __llvm_bitreverse(i); }
|
||||
reverse_bits :: proc(i: u16) -> u16 { __llvm_bitreverse :: proc(u16) -> u16 #foreign __llvm_core "llvm.bitreverse.i16"; return __llvm_bitreverse(i); }
|
||||
reverse_bits :: proc(i: i16) -> i16 { __llvm_bitreverse :: proc(i16) -> i16 #foreign __llvm_core "llvm.bitreverse.i16"; return __llvm_bitreverse(i); }
|
||||
reverse_bits :: proc(i: u32) -> u32 { __llvm_bitreverse :: proc(u32) -> u32 #foreign __llvm_core "llvm.bitreverse.i32"; return __llvm_bitreverse(i); }
|
||||
reverse_bits :: proc(i: i32) -> i32 { __llvm_bitreverse :: proc(i32) -> i32 #foreign __llvm_core "llvm.bitreverse.i32"; return __llvm_bitreverse(i); }
|
||||
reverse_bits :: proc(i: u64) -> u64 { __llvm_bitreverse :: proc(u64) -> u64 #foreign __llvm_core "llvm.bitreverse.i64"; return __llvm_bitreverse(i); }
|
||||
reverse_bits :: proc(i: i64) -> i64 { __llvm_bitreverse :: proc(i64) -> i64 #foreign __llvm_core "llvm.bitreverse.i64"; return __llvm_bitreverse(i); }
|
||||
reverse_bits :: proc(i: u128) -> u128 { __llvm_bitreverse :: proc(u128) -> u128 #foreign __llvm_core "llvm.bitreverse.i128";return __llvm_bitreverse(i); }
|
||||
reverse_bits :: proc(i: i128) -> i128 { __llvm_bitreverse :: proc(i128) -> i128 #foreign __llvm_core "llvm.bitreverse.i128";return __llvm_bitreverse(i); }
|
||||
reverse_bits :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(reverse_bits(u32(i))); } else { return uint(reverse_bits(u64(i))); } }
|
||||
reverse_bits :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(reverse_bits(i32(i))); } else { return int(reverse_bits(i64(i))); } }
|
||||
const reverse_bits = proc(i: u8) -> u8 { const __llvm_bitreverse = proc(u8) -> u8 #foreign __llvm_core "llvm.bitreverse.i8"; return __llvm_bitreverse(i); }
|
||||
const reverse_bits = proc(i: i8) -> i8 { const __llvm_bitreverse = proc(i8) -> i8 #foreign __llvm_core "llvm.bitreverse.i8"; return __llvm_bitreverse(i); }
|
||||
const reverse_bits = proc(i: u16) -> u16 { const __llvm_bitreverse = proc(u16) -> u16 #foreign __llvm_core "llvm.bitreverse.i16"; return __llvm_bitreverse(i); }
|
||||
const reverse_bits = proc(i: i16) -> i16 { const __llvm_bitreverse = proc(i16) -> i16 #foreign __llvm_core "llvm.bitreverse.i16"; return __llvm_bitreverse(i); }
|
||||
const reverse_bits = proc(i: u32) -> u32 { const __llvm_bitreverse = proc(u32) -> u32 #foreign __llvm_core "llvm.bitreverse.i32"; return __llvm_bitreverse(i); }
|
||||
const reverse_bits = proc(i: i32) -> i32 { const __llvm_bitreverse = proc(i32) -> i32 #foreign __llvm_core "llvm.bitreverse.i32"; return __llvm_bitreverse(i); }
|
||||
const reverse_bits = proc(i: u64) -> u64 { const __llvm_bitreverse = proc(u64) -> u64 #foreign __llvm_core "llvm.bitreverse.i64"; return __llvm_bitreverse(i); }
|
||||
const reverse_bits = proc(i: i64) -> i64 { const __llvm_bitreverse = proc(i64) -> i64 #foreign __llvm_core "llvm.bitreverse.i64"; return __llvm_bitreverse(i); }
|
||||
const reverse_bits = proc(i: u128) -> u128 { const __llvm_bitreverse = proc(u128) -> u128 #foreign __llvm_core "llvm.bitreverse.i128";return __llvm_bitreverse(i); }
|
||||
const reverse_bits = proc(i: i128) -> i128 { const __llvm_bitreverse = proc(i128) -> i128 #foreign __llvm_core "llvm.bitreverse.i128";return __llvm_bitreverse(i); }
|
||||
const reverse_bits = proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(reverse_bits(u32(i))); } else { return uint(reverse_bits(u64(i))); } }
|
||||
const reverse_bits = proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(reverse_bits(i32(i))); } else { return int(reverse_bits(i64(i))); } }
|
||||
|
||||
|
||||
byte_swap :: proc(u16) -> u16 #foreign __llvm_core "llvm.bswap.i16";
|
||||
byte_swap :: proc(i16) -> i16 #foreign __llvm_core "llvm.bswap.i16";
|
||||
byte_swap :: proc(u32) -> u32 #foreign __llvm_core "llvm.bswap.i32";
|
||||
byte_swap :: proc(i32) -> i32 #foreign __llvm_core "llvm.bswap.i32";
|
||||
byte_swap :: proc(u64) -> u64 #foreign __llvm_core "llvm.bswap.i64";
|
||||
byte_swap :: proc(i64) -> i64 #foreign __llvm_core "llvm.bswap.i64";
|
||||
byte_swap :: proc(u128) -> u128 #foreign __llvm_core "llvm.bswap.i128";
|
||||
byte_swap :: proc(i128) -> i128 #foreign __llvm_core "llvm.bswap.i128";
|
||||
byte_swap :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(byte_swap(u32(i))); } else { return uint(byte_swap(u64(i))); } }
|
||||
byte_swap :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(byte_swap(i32(i))); } else { return int(byte_swap(i64(i))); } }
|
||||
const byte_swap = proc(u16) -> u16 #foreign __llvm_core "llvm.bswap.i16";
|
||||
const byte_swap = proc(i16) -> i16 #foreign __llvm_core "llvm.bswap.i16";
|
||||
const byte_swap = proc(u32) -> u32 #foreign __llvm_core "llvm.bswap.i32";
|
||||
const byte_swap = proc(i32) -> i32 #foreign __llvm_core "llvm.bswap.i32";
|
||||
const byte_swap = proc(u64) -> u64 #foreign __llvm_core "llvm.bswap.i64";
|
||||
const byte_swap = proc(i64) -> i64 #foreign __llvm_core "llvm.bswap.i64";
|
||||
const byte_swap = proc(u128) -> u128 #foreign __llvm_core "llvm.bswap.i128";
|
||||
const byte_swap = proc(i128) -> i128 #foreign __llvm_core "llvm.bswap.i128";
|
||||
const byte_swap = proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(byte_swap(u32(i))); } else { return uint(byte_swap(u64(i))); } }
|
||||
const byte_swap = proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(byte_swap(i32(i))); } else { return int(byte_swap(i64(i))); } }
|
||||
|
||||
|
||||
from_be :: proc(i: u8) -> u8 { return i; }
|
||||
from_be :: proc(i: i8) -> i8 { return i; }
|
||||
from_be :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
from_be :: proc(i: i16) -> i16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
from_be :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
from_be :: proc(i: i32) -> i32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
from_be :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
from_be :: proc(i: i64) -> i64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
from_be :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
from_be :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
from_be :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
from_be :: proc(i: int) -> int { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const from_be = proc(i: u8) -> u8 { return i; }
|
||||
const from_be = proc(i: i8) -> i8 { return i; }
|
||||
const from_be = proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const from_be = proc(i: i16) -> i16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const from_be = proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const from_be = proc(i: i32) -> i32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const from_be = proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const from_be = proc(i: i64) -> i64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const from_be = proc(i: u128) -> u128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const from_be = proc(i: i128) -> i128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const from_be = proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const from_be = proc(i: int) -> int { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
|
||||
from_le :: proc(i: u8) -> u8 { return i; }
|
||||
from_le :: proc(i: i8) -> i8 { return i; }
|
||||
from_le :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
from_le :: proc(i: i16) -> i16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
from_le :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
from_le :: proc(i: i32) -> i32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
from_le :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
from_le :: proc(i: i64) -> i64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
from_le :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
from_le :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
from_le :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
from_le :: proc(i: int) -> int { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const from_le = proc(i: u8) -> u8 { return i; }
|
||||
const from_le = proc(i: i8) -> i8 { return i; }
|
||||
const from_le = proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const from_le = proc(i: i16) -> i16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const from_le = proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const from_le = proc(i: i32) -> i32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const from_le = proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const from_le = proc(i: i64) -> i64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const from_le = proc(i: u128) -> u128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const from_le = proc(i: i128) -> i128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const from_le = proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const from_le = proc(i: int) -> int { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
|
||||
to_be :: proc(i: u8) -> u8 { return i; }
|
||||
to_be :: proc(i: i8) -> i8 { return i; }
|
||||
to_be :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
to_be :: proc(i: i16) -> i16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
to_be :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
to_be :: proc(i: i32) -> i32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
to_be :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
to_be :: proc(i: i64) -> i64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
to_be :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
to_be :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
to_be :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
to_be :: proc(i: int) -> int { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const to_be = proc(i: u8) -> u8 { return i; }
|
||||
const to_be = proc(i: i8) -> i8 { return i; }
|
||||
const to_be = proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const to_be = proc(i: i16) -> i16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const to_be = proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const to_be = proc(i: i32) -> i32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const to_be = proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const to_be = proc(i: i64) -> i64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const to_be = proc(i: u128) -> u128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const to_be = proc(i: i128) -> i128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const to_be = proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
const to_be = proc(i: int) -> int { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
|
||||
|
||||
|
||||
to_le :: proc(i: u8) -> u8 { return i; }
|
||||
to_le :: proc(i: i8) -> i8 { return i; }
|
||||
to_le :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
to_le :: proc(i: i16) -> i16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
to_le :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
to_le :: proc(i: i32) -> i32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
to_le :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
to_le :: proc(i: i64) -> i64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
to_le :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
to_le :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
to_le :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
to_le :: proc(i: int) -> int { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const to_le = proc(i: u8) -> u8 { return i; }
|
||||
const to_le = proc(i: i8) -> i8 { return i; }
|
||||
const to_le = proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const to_le = proc(i: i16) -> i16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const to_le = proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const to_le = proc(i: i32) -> i32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const to_le = proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const to_le = proc(i: i64) -> i64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const to_le = proc(i: u128) -> u128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const to_le = proc(i: i128) -> i128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const to_le = proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
const to_le = proc(i: int) -> int { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
|
||||
|
||||
|
||||
overflowing_add :: proc(lhs, rhs: u8) -> (u8, bool) { op :: proc(u8, u8) -> (u8, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i8"; return op(lhs, rhs); }
|
||||
overflowing_add :: proc(lhs, rhs: i8) -> (i8, bool) { op :: proc(i8, i8) -> (i8, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i8"; return op(lhs, rhs); }
|
||||
overflowing_add :: proc(lhs, rhs: u16) -> (u16, bool) { op :: proc(u16, u16) -> (u16, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i16"; return op(lhs, rhs); }
|
||||
overflowing_add :: proc(lhs, rhs: i16) -> (i16, bool) { op :: proc(i16, i16) -> (i16, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i16"; return op(lhs, rhs); }
|
||||
overflowing_add :: proc(lhs, rhs: u32) -> (u32, bool) { op :: proc(u32, u32) -> (u32, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i32"; return op(lhs, rhs); }
|
||||
overflowing_add :: proc(lhs, rhs: i32) -> (i32, bool) { op :: proc(i32, i32) -> (i32, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i32"; return op(lhs, rhs); }
|
||||
overflowing_add :: proc(lhs, rhs: u64) -> (u64, bool) { op :: proc(u64, u64) -> (u64, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i64"; return op(lhs, rhs); }
|
||||
overflowing_add :: proc(lhs, rhs: i64) -> (i64, bool) { op :: proc(i64, i64) -> (i64, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i64"; return op(lhs, rhs); }
|
||||
overflowing_add :: proc(lhs, rhs: u128) -> (u128, bool) { op :: proc(u128, u128) -> (u128, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i128"; return op(lhs, rhs); }
|
||||
overflowing_add :: proc(lhs, rhs: i128) -> (i128, bool) { op :: proc(i128, i128) -> (i128, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i128"; return op(lhs, rhs); }
|
||||
overflowing_add :: proc(lhs, rhs: uint) -> (uint, bool) {
|
||||
const overflowing_add = proc(lhs, rhs: u8) -> (u8, bool) { const op = proc(u8, u8) -> (u8, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i8"; return op(lhs, rhs); }
|
||||
const overflowing_add = proc(lhs, rhs: i8) -> (i8, bool) { const op = proc(i8, i8) -> (i8, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i8"; return op(lhs, rhs); }
|
||||
const overflowing_add = proc(lhs, rhs: u16) -> (u16, bool) { const op = proc(u16, u16) -> (u16, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i16"; return op(lhs, rhs); }
|
||||
const overflowing_add = proc(lhs, rhs: i16) -> (i16, bool) { const op = proc(i16, i16) -> (i16, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i16"; return op(lhs, rhs); }
|
||||
const overflowing_add = proc(lhs, rhs: u32) -> (u32, bool) { const op = proc(u32, u32) -> (u32, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i32"; return op(lhs, rhs); }
|
||||
const overflowing_add = proc(lhs, rhs: i32) -> (i32, bool) { const op = proc(i32, i32) -> (i32, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i32"; return op(lhs, rhs); }
|
||||
const overflowing_add = proc(lhs, rhs: u64) -> (u64, bool) { const op = proc(u64, u64) -> (u64, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i64"; return op(lhs, rhs); }
|
||||
const overflowing_add = proc(lhs, rhs: i64) -> (i64, bool) { const op = proc(i64, i64) -> (i64, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i64"; return op(lhs, rhs); }
|
||||
const overflowing_add = proc(lhs, rhs: u128) -> (u128, bool) { const op = proc(u128, u128) -> (u128, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i128"; return op(lhs, rhs); }
|
||||
const overflowing_add = proc(lhs, rhs: i128) -> (i128, bool) { const op = proc(i128, i128) -> (i128, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i128"; return op(lhs, rhs); }
|
||||
const overflowing_add = proc(lhs, rhs: uint) -> (uint, bool) {
|
||||
when size_of(uint) == size_of(u32) {
|
||||
x, ok := overflowing_add(u32(lhs), u32(rhs));
|
||||
var x, ok = overflowing_add(u32(lhs), u32(rhs));
|
||||
return uint(x), ok;
|
||||
} else {
|
||||
x, ok := overflowing_add(u64(lhs), u64(rhs));
|
||||
var x, ok = overflowing_add(u64(lhs), u64(rhs));
|
||||
return uint(x), ok;
|
||||
}
|
||||
}
|
||||
overflowing_add :: proc(lhs, rhs: int) -> (int, bool) {
|
||||
const overflowing_add = proc(lhs, rhs: int) -> (int, bool) {
|
||||
when size_of(int) == size_of(i32) {
|
||||
x, ok := overflowing_add(i32(lhs), i32(rhs));
|
||||
var x, ok = overflowing_add(i32(lhs), i32(rhs));
|
||||
return int(x), ok;
|
||||
} else {
|
||||
x, ok := overflowing_add(i64(lhs), i64(rhs));
|
||||
var x, ok = overflowing_add(i64(lhs), i64(rhs));
|
||||
return int(x), ok;
|
||||
}
|
||||
}
|
||||
|
||||
overflowing_sub :: proc(lhs, rhs: u8) -> (u8, bool) { op :: proc(u8, u8) -> (u8, bool) #foreign __llvm_core "llvm.usub.with.overflow.i8"; return op(lhs, rhs); }
|
||||
overflowing_sub :: proc(lhs, rhs: i8) -> (i8, bool) { op :: proc(i8, i8) -> (i8, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i8"; return op(lhs, rhs); }
|
||||
overflowing_sub :: proc(lhs, rhs: u16) -> (u16, bool) { op :: proc(u16, u16) -> (u16, bool) #foreign __llvm_core "llvm.usub.with.overflow.i16"; return op(lhs, rhs); }
|
||||
overflowing_sub :: proc(lhs, rhs: i16) -> (i16, bool) { op :: proc(i16, i16) -> (i16, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i16"; return op(lhs, rhs); }
|
||||
overflowing_sub :: proc(lhs, rhs: u32) -> (u32, bool) { op :: proc(u32, u32) -> (u32, bool) #foreign __llvm_core "llvm.usub.with.overflow.i32"; return op(lhs, rhs); }
|
||||
overflowing_sub :: proc(lhs, rhs: i32) -> (i32, bool) { op :: proc(i32, i32) -> (i32, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i32"; return op(lhs, rhs); }
|
||||
overflowing_sub :: proc(lhs, rhs: u64) -> (u64, bool) { op :: proc(u64, u64) -> (u64, bool) #foreign __llvm_core "llvm.usub.with.overflow.i64"; return op(lhs, rhs); }
|
||||
overflowing_sub :: proc(lhs, rhs: i64) -> (i64, bool) { op :: proc(i64, i64) -> (i64, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i64"; return op(lhs, rhs); }
|
||||
overflowing_sub :: proc(lhs, rhs: u128) -> (u128, bool) { op :: proc(u128, u128) -> (u128, bool) #foreign __llvm_core "llvm.usub.with.overflow.i128"; return op(lhs, rhs); }
|
||||
overflowing_sub :: proc(lhs, rhs: i128) -> (i128, bool) { op :: proc(i128, i128) -> (i128, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i128"; return op(lhs, rhs); }
|
||||
overflowing_sub :: proc(lhs, rhs: uint) -> (uint, bool) {
|
||||
const overflowing_sub = proc(lhs, rhs: u8) -> (u8, bool) { const op = proc(u8, u8) -> (u8, bool) #foreign __llvm_core "llvm.usub.with.overflow.i8"; return op(lhs, rhs); }
|
||||
const overflowing_sub = proc(lhs, rhs: i8) -> (i8, bool) { const op = proc(i8, i8) -> (i8, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i8"; return op(lhs, rhs); }
|
||||
const overflowing_sub = proc(lhs, rhs: u16) -> (u16, bool) { const op = proc(u16, u16) -> (u16, bool) #foreign __llvm_core "llvm.usub.with.overflow.i16"; return op(lhs, rhs); }
|
||||
const overflowing_sub = proc(lhs, rhs: i16) -> (i16, bool) { const op = proc(i16, i16) -> (i16, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i16"; return op(lhs, rhs); }
|
||||
const overflowing_sub = proc(lhs, rhs: u32) -> (u32, bool) { const op = proc(u32, u32) -> (u32, bool) #foreign __llvm_core "llvm.usub.with.overflow.i32"; return op(lhs, rhs); }
|
||||
const overflowing_sub = proc(lhs, rhs: i32) -> (i32, bool) { const op = proc(i32, i32) -> (i32, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i32"; return op(lhs, rhs); }
|
||||
const overflowing_sub = proc(lhs, rhs: u64) -> (u64, bool) { const op = proc(u64, u64) -> (u64, bool) #foreign __llvm_core "llvm.usub.with.overflow.i64"; return op(lhs, rhs); }
|
||||
const overflowing_sub = proc(lhs, rhs: i64) -> (i64, bool) { const op = proc(i64, i64) -> (i64, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i64"; return op(lhs, rhs); }
|
||||
const overflowing_sub = proc(lhs, rhs: u128) -> (u128, bool) { const op = proc(u128, u128) -> (u128, bool) #foreign __llvm_core "llvm.usub.with.overflow.i128"; return op(lhs, rhs); }
|
||||
const overflowing_sub = proc(lhs, rhs: i128) -> (i128, bool) { const op = proc(i128, i128) -> (i128, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i128"; return op(lhs, rhs); }
|
||||
const overflowing_sub = proc(lhs, rhs: uint) -> (uint, bool) {
|
||||
when size_of(uint) == size_of(u32) {
|
||||
x, ok := overflowing_sub(u32(lhs), u32(rhs));
|
||||
var x, ok = overflowing_sub(u32(lhs), u32(rhs));
|
||||
return uint(x), ok;
|
||||
} else {
|
||||
x, ok := overflowing_sub(u64(lhs), u64(rhs));
|
||||
var x, ok = overflowing_sub(u64(lhs), u64(rhs));
|
||||
return uint(x), ok;
|
||||
}
|
||||
}
|
||||
overflowing_sub :: proc(lhs, rhs: int) -> (int, bool) {
|
||||
const overflowing_sub = proc(lhs, rhs: int) -> (int, bool) {
|
||||
when size_of(int) == size_of(i32) {
|
||||
x, ok := overflowing_sub(i32(lhs), i32(rhs));
|
||||
var x, ok = overflowing_sub(i32(lhs), i32(rhs));
|
||||
return int(x), ok;
|
||||
} else {
|
||||
x, ok := overflowing_sub(i64(lhs), i64(rhs));
|
||||
var x, ok = overflowing_sub(i64(lhs), i64(rhs));
|
||||
return int(x), ok;
|
||||
}
|
||||
}
|
||||
|
||||
overflowing_mul :: proc(lhs, rhs: u8) -> (u8, bool) { op :: proc(u8, u8) -> (u8, bool) #foreign __llvm_core "llvm.umul.with.overflow.i8"; return op(lhs, rhs); }
|
||||
overflowing_mul :: proc(lhs, rhs: i8) -> (i8, bool) { op :: proc(i8, i8) -> (i8, bool) #foreign __llvm_core "llvm.smul.with.overflow.i8"; return op(lhs, rhs); }
|
||||
overflowing_mul :: proc(lhs, rhs: u16) -> (u16, bool) { op :: proc(u16, u16) -> (u16, bool) #foreign __llvm_core "llvm.umul.with.overflow.i16"; return op(lhs, rhs); }
|
||||
overflowing_mul :: proc(lhs, rhs: i16) -> (i16, bool) { op :: proc(i16, i16) -> (i16, bool) #foreign __llvm_core "llvm.smul.with.overflow.i16"; return op(lhs, rhs); }
|
||||
overflowing_mul :: proc(lhs, rhs: u32) -> (u32, bool) { op :: proc(u32, u32) -> (u32, bool) #foreign __llvm_core "llvm.umul.with.overflow.i32"; return op(lhs, rhs); }
|
||||
overflowing_mul :: proc(lhs, rhs: i32) -> (i32, bool) { op :: proc(i32, i32) -> (i32, bool) #foreign __llvm_core "llvm.smul.with.overflow.i32"; return op(lhs, rhs); }
|
||||
overflowing_mul :: proc(lhs, rhs: u64) -> (u64, bool) { op :: proc(u64, u64) -> (u64, bool) #foreign __llvm_core "llvm.umul.with.overflow.i64"; return op(lhs, rhs); }
|
||||
overflowing_mul :: proc(lhs, rhs: i64) -> (i64, bool) { op :: proc(i64, i64) -> (i64, bool) #foreign __llvm_core "llvm.smul.with.overflow.i64"; return op(lhs, rhs); }
|
||||
overflowing_mul :: proc(lhs, rhs: u128) -> (u128, bool) { op :: proc(u128, u128) -> (u128, bool) #foreign __llvm_core "llvm.umul.with.overflow.i128"; return op(lhs, rhs); }
|
||||
overflowing_mul :: proc(lhs, rhs: i128) -> (i128, bool) { op :: proc(i128, i128) -> (i128, bool) #foreign __llvm_core "llvm.smul.with.overflow.i128"; return op(lhs, rhs); }
|
||||
overflowing_mul :: proc(lhs, rhs: uint) -> (uint, bool) {
|
||||
const overflowing_mul = proc(lhs, rhs: u8) -> (u8, bool) { const op = proc(u8, u8) -> (u8, bool) #foreign __llvm_core "llvm.umul.with.overflow.i8"; return op(lhs, rhs); }
|
||||
const overflowing_mul = proc(lhs, rhs: i8) -> (i8, bool) { const op = proc(i8, i8) -> (i8, bool) #foreign __llvm_core "llvm.smul.with.overflow.i8"; return op(lhs, rhs); }
|
||||
const overflowing_mul = proc(lhs, rhs: u16) -> (u16, bool) { const op = proc(u16, u16) -> (u16, bool) #foreign __llvm_core "llvm.umul.with.overflow.i16"; return op(lhs, rhs); }
|
||||
const overflowing_mul = proc(lhs, rhs: i16) -> (i16, bool) { const op = proc(i16, i16) -> (i16, bool) #foreign __llvm_core "llvm.smul.with.overflow.i16"; return op(lhs, rhs); }
|
||||
const overflowing_mul = proc(lhs, rhs: u32) -> (u32, bool) { const op = proc(u32, u32) -> (u32, bool) #foreign __llvm_core "llvm.umul.with.overflow.i32"; return op(lhs, rhs); }
|
||||
const overflowing_mul = proc(lhs, rhs: i32) -> (i32, bool) { const op = proc(i32, i32) -> (i32, bool) #foreign __llvm_core "llvm.smul.with.overflow.i32"; return op(lhs, rhs); }
|
||||
const overflowing_mul = proc(lhs, rhs: u64) -> (u64, bool) { const op = proc(u64, u64) -> (u64, bool) #foreign __llvm_core "llvm.umul.with.overflow.i64"; return op(lhs, rhs); }
|
||||
const overflowing_mul = proc(lhs, rhs: i64) -> (i64, bool) { const op = proc(i64, i64) -> (i64, bool) #foreign __llvm_core "llvm.smul.with.overflow.i64"; return op(lhs, rhs); }
|
||||
const overflowing_mul = proc(lhs, rhs: u128) -> (u128, bool) { const op = proc(u128, u128) -> (u128, bool) #foreign __llvm_core "llvm.umul.with.overflow.i128"; return op(lhs, rhs); }
|
||||
const overflowing_mul = proc(lhs, rhs: i128) -> (i128, bool) { const op = proc(i128, i128) -> (i128, bool) #foreign __llvm_core "llvm.smul.with.overflow.i128"; return op(lhs, rhs); }
|
||||
const overflowing_mul = proc(lhs, rhs: uint) -> (uint, bool) {
|
||||
when size_of(uint) == size_of(u32) {
|
||||
x, ok := overflowing_mul(u32(lhs), u32(rhs));
|
||||
var x, ok = overflowing_mul(u32(lhs), u32(rhs));
|
||||
return uint(x), ok;
|
||||
} else {
|
||||
x, ok := overflowing_mul(u64(lhs), u64(rhs));
|
||||
var x, ok = overflowing_mul(u64(lhs), u64(rhs));
|
||||
return uint(x), ok;
|
||||
}
|
||||
}
|
||||
overflowing_mul :: proc(lhs, rhs: int) -> (int, bool) {
|
||||
const overflowing_mul = proc(lhs, rhs: int) -> (int, bool) {
|
||||
when size_of(int) == size_of(i32) {
|
||||
x, ok := overflowing_mul(i32(lhs), i32(rhs));
|
||||
var x, ok = overflowing_mul(i32(lhs), i32(rhs));
|
||||
return int(x), ok;
|
||||
} else {
|
||||
x, ok := overflowing_mul(i64(lhs), i64(rhs));
|
||||
var x, ok = overflowing_mul(i64(lhs), i64(rhs));
|
||||
return int(x), ok;
|
||||
}
|
||||
}
|
||||
|
||||
is_power_of_two :: proc(i: u8) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
is_power_of_two :: proc(i: i8) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
is_power_of_two :: proc(i: u16) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
is_power_of_two :: proc(i: i16) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
is_power_of_two :: proc(i: u32) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
is_power_of_two :: proc(i: i32) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
is_power_of_two :: proc(i: u64) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
is_power_of_two :: proc(i: i64) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
is_power_of_two :: proc(i: u128) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
is_power_of_two :: proc(i: i128) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
is_power_of_two :: proc(i: uint) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
is_power_of_two :: proc(i: int) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
const is_power_of_two = proc(i: u8) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
const is_power_of_two = proc(i: i8) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
const is_power_of_two = proc(i: u16) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
const is_power_of_two = proc(i: i16) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
const is_power_of_two = proc(i: u32) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
const is_power_of_two = proc(i: i32) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
const is_power_of_two = proc(i: u64) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
const is_power_of_two = proc(i: i64) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
const is_power_of_two = proc(i: u128) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
const is_power_of_two = proc(i: i128) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
const is_power_of_two = proc(i: uint) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
const is_power_of_two = proc(i: int) -> bool { return i > 0 && (i & (i-1)) == 0; }
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
// Multiple precision decimal numbers
|
||||
// NOTE: This is only for floating point printing and nothing else
|
||||
|
||||
Decimal :: struct {
|
||||
const Decimal = struct {
|
||||
digits: [384]u8, // big-endian digits
|
||||
count: int,
|
||||
decimal_point: int,
|
||||
neg, trunc: bool,
|
||||
}
|
||||
|
||||
decimal_to_string :: proc(buf: []u8, a: ^Decimal) -> string {
|
||||
digit_zero :: proc(buf: []u8) -> int {
|
||||
const decimal_to_string = proc(buf: []u8, a: ^Decimal) -> string {
|
||||
const digit_zero = proc(buf: []u8) -> int {
|
||||
for _, i in buf {
|
||||
buf[i] = '0';
|
||||
}
|
||||
@@ -18,7 +18,7 @@ decimal_to_string :: proc(buf: []u8, a: ^Decimal) -> string {
|
||||
}
|
||||
|
||||
|
||||
n := 10 + a.count + abs(a.decimal_point);
|
||||
var n = 10 + a.count + abs(a.decimal_point);
|
||||
|
||||
// TODO(bill): make this work with a buffer that's not big enough
|
||||
assert(len(buf) >= n);
|
||||
@@ -29,7 +29,7 @@ decimal_to_string :: proc(buf: []u8, a: ^Decimal) -> string {
|
||||
return string(buf[0..<1]);
|
||||
}
|
||||
|
||||
w := 0;
|
||||
var w = 0;
|
||||
if a.decimal_point <= 0 {
|
||||
buf[w] = '0'; w++;
|
||||
buf[w] = '.'; w++;
|
||||
@@ -48,7 +48,7 @@ decimal_to_string :: proc(buf: []u8, a: ^Decimal) -> string {
|
||||
}
|
||||
|
||||
// trim trailing zeros
|
||||
trim :: proc(a: ^Decimal) {
|
||||
const trim = proc(a: ^Decimal) {
|
||||
for a.count > 0 && a.digits[a.count-1] == '0' {
|
||||
a.count--;
|
||||
}
|
||||
@@ -58,11 +58,11 @@ trim :: proc(a: ^Decimal) {
|
||||
}
|
||||
|
||||
|
||||
assign :: proc(a: ^Decimal, i: u64) {
|
||||
buf: [32]u8;
|
||||
n := 0;
|
||||
const assign = proc(a: ^Decimal, i: u64) {
|
||||
var buf: [32]u8;
|
||||
var n = 0;
|
||||
for i > 0 {
|
||||
j := i/10;
|
||||
var j = i/10;
|
||||
i -= 10*j;
|
||||
buf[n] = u8('0'+i);
|
||||
n++;
|
||||
@@ -78,14 +78,14 @@ assign :: proc(a: ^Decimal, i: u64) {
|
||||
trim(a);
|
||||
}
|
||||
|
||||
uint_size :: 8*size_of(uint);
|
||||
max_shift :: uint_size-4;
|
||||
const uint_size = 8*size_of(uint);
|
||||
const max_shift = uint_size-4;
|
||||
|
||||
shift_right :: proc(a: ^Decimal, k: uint) {
|
||||
r := 0; // read index
|
||||
w := 0; // write index
|
||||
const shift_right = proc(a: ^Decimal, k: uint) {
|
||||
var r = 0; // read index
|
||||
var w = 0; // write index
|
||||
|
||||
n: uint;
|
||||
var n: uint;
|
||||
for ; n>>k == 0; r++ {
|
||||
if r >= a.count {
|
||||
if n == 0 {
|
||||
@@ -99,16 +99,16 @@ shift_right :: proc(a: ^Decimal, k: uint) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
c := uint(a.digits[r]);
|
||||
var c = uint(a.digits[r]);
|
||||
n = n*10 + c - '0';
|
||||
}
|
||||
a.decimal_point -= r-1;
|
||||
|
||||
mask: uint = (1<<k) - 1;
|
||||
var mask: uint = (1<<k) - 1;
|
||||
|
||||
for ; r < a.count; r++ {
|
||||
c := uint(a.digits[r]);
|
||||
dig := n>>k;
|
||||
var c = uint(a.digits[r]);
|
||||
var dig = n>>k;
|
||||
n &= mask;
|
||||
a.digits[w] = u8('0' + dig);
|
||||
w++;
|
||||
@@ -116,7 +116,7 @@ shift_right :: proc(a: ^Decimal, k: uint) {
|
||||
}
|
||||
|
||||
for n > 0 {
|
||||
dig := n>>k;
|
||||
var dig = n>>k;
|
||||
n &= mask;
|
||||
if w < len(a.digits) {
|
||||
a.digits[w] = u8('0' + dig);
|
||||
@@ -132,17 +132,17 @@ shift_right :: proc(a: ^Decimal, k: uint) {
|
||||
trim(a);
|
||||
}
|
||||
|
||||
shift_left :: proc(a: ^Decimal, k: uint) {
|
||||
delta := int(k/4);
|
||||
const shift_left = proc(a: ^Decimal, k: uint) {
|
||||
var delta = int(k/4);
|
||||
|
||||
r := a.count; // read index
|
||||
w := a.count+delta; // write index
|
||||
var r = a.count; // read index
|
||||
var w = a.count+delta; // write index
|
||||
|
||||
n: uint;
|
||||
var n: uint;
|
||||
for r--; r >= 0; r-- {
|
||||
n += (uint(a.digits[r]) - '0') << k;
|
||||
quo := n/10;
|
||||
rem := n - 10*quo;
|
||||
var quo = n/10;
|
||||
var rem = n - 10*quo;
|
||||
w--;
|
||||
if w < len(a.digits) {
|
||||
a.digits[w] = u8('0' + rem);
|
||||
@@ -153,8 +153,8 @@ shift_left :: proc(a: ^Decimal, k: uint) {
|
||||
}
|
||||
|
||||
for n > 0 {
|
||||
quo := n/10;
|
||||
rem := n - 10*quo;
|
||||
var quo = n/10;
|
||||
var rem = n - 10*quo;
|
||||
w--;
|
||||
if 0 <= w && w < len(a.digits) {
|
||||
a.digits[w] = u8('0' + rem);
|
||||
@@ -170,7 +170,7 @@ shift_left :: proc(a: ^Decimal, k: uint) {
|
||||
trim(a);
|
||||
}
|
||||
|
||||
shift :: proc(a: ^Decimal, k: int) {
|
||||
const shift = proc(a: ^Decimal, k: int) {
|
||||
match {
|
||||
case a.count == 0:
|
||||
// no need to update
|
||||
@@ -191,7 +191,7 @@ shift :: proc(a: ^Decimal, k: int) {
|
||||
}
|
||||
}
|
||||
|
||||
can_round_up :: proc(a: ^Decimal, nd: int) -> bool {
|
||||
const can_round_up = proc(a: ^Decimal, nd: int) -> bool {
|
||||
if nd < 0 || nd >= a.count { return false ; }
|
||||
if a.digits[nd] == '5' && nd+1 == a.count {
|
||||
if a.trunc {
|
||||
@@ -203,7 +203,7 @@ can_round_up :: proc(a: ^Decimal, nd: int) -> bool {
|
||||
return a.digits[nd] >= '5';
|
||||
}
|
||||
|
||||
round :: proc(a: ^Decimal, nd: int) {
|
||||
const round = proc(a: ^Decimal, nd: int) {
|
||||
if nd < 0 || nd >= a.count { return; }
|
||||
if can_round_up(a, nd) {
|
||||
round_up(a, nd);
|
||||
@@ -212,11 +212,11 @@ round :: proc(a: ^Decimal, nd: int) {
|
||||
}
|
||||
}
|
||||
|
||||
round_up :: proc(a: ^Decimal, nd: int) {
|
||||
const round_up = proc(a: ^Decimal, nd: int) {
|
||||
if nd < 0 || nd >= a.count { return; }
|
||||
|
||||
for i := nd-1; i >= 0; i-- {
|
||||
if c := a.digits[i]; c < '9' {
|
||||
for var i = nd-1; i >= 0; i-- {
|
||||
if var c = a.digits[i]; c < '9' {
|
||||
a.digits[i]++;
|
||||
a.count = i+1;
|
||||
return;
|
||||
@@ -229,7 +229,7 @@ round_up :: proc(a: ^Decimal, nd: int) {
|
||||
a.decimal_point++;
|
||||
}
|
||||
|
||||
round_down :: proc(a: ^Decimal, nd: int) {
|
||||
const round_down = proc(a: ^Decimal, nd: int) {
|
||||
if nd < 0 || nd >= a.count { return; }
|
||||
a.count = nd;
|
||||
trim(a);
|
||||
@@ -237,13 +237,13 @@ round_down :: proc(a: ^Decimal, nd: int) {
|
||||
|
||||
|
||||
// Extract integer part, rounded appropriately. There are no guarantees about overflow.
|
||||
rounded_integer :: proc(a: ^Decimal) -> u64 {
|
||||
const rounded_integer = proc(a: ^Decimal) -> u64 {
|
||||
if a.decimal_point > 20 {
|
||||
return 0xffff_ffff_ffff_ffff;
|
||||
}
|
||||
i: int;
|
||||
n: u64 = 0;
|
||||
m := min(a.decimal_point, a.count);
|
||||
var i: int;
|
||||
var n: u64 = 0;
|
||||
var m = min(a.decimal_point, a.count);
|
||||
for i = 0; i < m; i++ {
|
||||
n = n*10 + u64(a.digits[i]-'0');
|
||||
}
|
||||
|
||||
324
core/fmt.odin
324
core/fmt.odin
@@ -6,14 +6,14 @@
|
||||
#import "raw.odin";
|
||||
|
||||
|
||||
_BUFFER_SIZE :: 1<<12;
|
||||
const _BUFFER_SIZE = 1<<12;
|
||||
|
||||
StringBuffer :: union {
|
||||
const StringBuffer = union {
|
||||
Static {buf: []u8},
|
||||
Dynamic{buf: [dynamic]u8},
|
||||
}
|
||||
|
||||
FmtInfo :: struct {
|
||||
const FmtInfo = struct {
|
||||
minus: bool,
|
||||
plus: bool,
|
||||
space: bool,
|
||||
@@ -33,14 +33,14 @@ FmtInfo :: struct {
|
||||
}
|
||||
|
||||
|
||||
make_string_buffer_from_slice :: proc(b: []u8) -> StringBuffer {
|
||||
const make_string_buffer_from_slice = proc(b: []u8) -> StringBuffer {
|
||||
return StringBuffer.Static{b};
|
||||
}
|
||||
|
||||
make_string_dynamic_buffer :: proc() -> StringBuffer {
|
||||
const make_string_dynamic_buffer = proc() -> StringBuffer {
|
||||
return StringBuffer.Dynamic{make([dynamic]u8)};
|
||||
}
|
||||
string_buffer_data :: proc(buf: ^StringBuffer) -> []u8 {
|
||||
const string_buffer_data = proc(buf: ^StringBuffer) -> []u8 {
|
||||
match b in buf {
|
||||
case StringBuffer.Static:
|
||||
return b.buf[..];
|
||||
@@ -49,7 +49,7 @@ string_buffer_data :: proc(buf: ^StringBuffer) -> []u8 {
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
string_buffer_data :: proc(buf: StringBuffer) -> []u8 {
|
||||
const string_buffer_data = proc(buf: StringBuffer) -> []u8 {
|
||||
match b in buf {
|
||||
case StringBuffer.Static:
|
||||
return b.buf[..];
|
||||
@@ -58,15 +58,15 @@ string_buffer_data :: proc(buf: StringBuffer) -> []u8 {
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
to_string :: proc(buf: StringBuffer) -> string {
|
||||
const to_string = proc(buf: StringBuffer) -> string {
|
||||
return string(string_buffer_data(buf));
|
||||
}
|
||||
|
||||
|
||||
write_string :: proc(buf: ^StringBuffer, s: string) {
|
||||
const write_string = proc(buf: ^StringBuffer, s: string) {
|
||||
write_bytes(buf, []u8(s));
|
||||
}
|
||||
write_bytes :: proc(buf: ^StringBuffer, data: []u8) {
|
||||
const write_bytes = proc(buf: ^StringBuffer, data: []u8) {
|
||||
match b in buf {
|
||||
case StringBuffer.Static:
|
||||
append(b.buf, ..data);
|
||||
@@ -74,7 +74,7 @@ write_bytes :: proc(buf: ^StringBuffer, data: []u8) {
|
||||
append(b.buf, ..data);
|
||||
}
|
||||
}
|
||||
write_byte :: proc(buf: ^StringBuffer, data: u8) {
|
||||
const write_byte = proc(buf: ^StringBuffer, data: u8) {
|
||||
match b in buf {
|
||||
case StringBuffer.Static:
|
||||
append(b.buf, data);
|
||||
@@ -82,79 +82,79 @@ write_byte :: proc(buf: ^StringBuffer, data: u8) {
|
||||
append(b.buf, data);
|
||||
}
|
||||
}
|
||||
write_rune :: proc(buf: ^StringBuffer, r: rune) {
|
||||
const write_rune = proc(buf: ^StringBuffer, r: rune) {
|
||||
if r < utf8.RUNE_SELF {
|
||||
write_byte(buf, u8(r));
|
||||
return;
|
||||
}
|
||||
|
||||
b, n := utf8.encode_rune(r);
|
||||
var b, n = utf8.encode_rune(r);
|
||||
write_bytes(buf, b[0..<n]);
|
||||
}
|
||||
|
||||
write_int :: proc(buf: ^StringBuffer, i: i128, base: int) {
|
||||
b: [129]u8;
|
||||
s := strconv.append_bits(b[0..<0], u128(i), base, true, 128, strconv.digits, 0);
|
||||
const write_int = proc(buf: ^StringBuffer, i: i128, base: int) {
|
||||
var b: [129]u8;
|
||||
var s = strconv.append_bits(b[0..<0], u128(i), base, true, 128, strconv.digits, 0);
|
||||
write_string(buf, s);
|
||||
}
|
||||
write_int :: proc(buf: ^StringBuffer, i: i64, base: int) {
|
||||
b: [129]u8;
|
||||
s := strconv.append_bits(b[0..<0], u128(i), base, true, 64, strconv.digits, 0);
|
||||
const write_int = proc(buf: ^StringBuffer, i: i64, base: int) {
|
||||
var b: [129]u8;
|
||||
var s = strconv.append_bits(b[0..<0], u128(i), base, true, 64, strconv.digits, 0);
|
||||
write_string(buf, s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
fprint :: proc(fd: os.Handle, args: ..any) -> int {
|
||||
data: [_BUFFER_SIZE]u8;
|
||||
buf := make_string_buffer_from_slice(data[0..<0]);
|
||||
const fprint = proc(fd: os.Handle, args: ..any) -> int {
|
||||
var data: [_BUFFER_SIZE]u8;
|
||||
var buf = make_string_buffer_from_slice(data[0..<0]);
|
||||
sbprint(&buf, ..args);
|
||||
res := string_buffer_data(buf);
|
||||
var res = string_buffer_data(buf);
|
||||
os.write(fd, res);
|
||||
return len(res);
|
||||
}
|
||||
|
||||
fprintln :: proc(fd: os.Handle, args: ..any) -> int {
|
||||
data: [_BUFFER_SIZE]u8;
|
||||
buf := make_string_buffer_from_slice(data[0..<0]);
|
||||
const fprintln = proc(fd: os.Handle, args: ..any) -> int {
|
||||
var data: [_BUFFER_SIZE]u8;
|
||||
var buf = make_string_buffer_from_slice(data[0..<0]);
|
||||
sbprintln(&buf, ..args);
|
||||
res := string_buffer_data(buf);
|
||||
var res = string_buffer_data(buf);
|
||||
os.write(fd, res);
|
||||
return len(res);
|
||||
}
|
||||
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
|
||||
data: [_BUFFER_SIZE]u8;
|
||||
buf := make_string_buffer_from_slice(data[0..<0]);
|
||||
const fprintf = proc(fd: os.Handle, fmt: string, args: ..any) -> int {
|
||||
var data: [_BUFFER_SIZE]u8;
|
||||
var buf = make_string_buffer_from_slice(data[0..<0]);
|
||||
sbprintf(&buf, fmt, ..args);
|
||||
res := string_buffer_data(buf);
|
||||
var res = string_buffer_data(buf);
|
||||
os.write(fd, res);
|
||||
return len(res);
|
||||
}
|
||||
|
||||
|
||||
// print* procedures return the number of bytes written
|
||||
print :: proc(args: ..any) -> int { return fprint(os.stdout, ..args); }
|
||||
print_err :: proc(args: ..any) -> int { return fprint(os.stderr, ..args); }
|
||||
println :: proc(args: ..any) -> int { return fprintln(os.stdout, ..args); }
|
||||
println_err :: proc(args: ..any) -> int { return fprintln(os.stderr, ..args); }
|
||||
printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args); }
|
||||
printf_err :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args); }
|
||||
const print = proc(args: ..any) -> int { return fprint(os.stdout, ..args); }
|
||||
const print_err = proc(args: ..any) -> int { return fprint(os.stderr, ..args); }
|
||||
const println = proc(args: ..any) -> int { return fprintln(os.stdout, ..args); }
|
||||
const println_err = proc(args: ..any) -> int { return fprintln(os.stderr, ..args); }
|
||||
const printf = proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args); }
|
||||
const printf_err = proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args); }
|
||||
|
||||
|
||||
// aprint* procedures return a string that was allocated with the current context
|
||||
// They must be freed accordingly
|
||||
aprint :: proc(args: ..any) -> string {
|
||||
buf := make_string_dynamic_buffer();
|
||||
const aprint = proc(args: ..any) -> string {
|
||||
var buf = make_string_dynamic_buffer();
|
||||
sbprint(&buf, ..args);
|
||||
return to_string(buf);
|
||||
}
|
||||
aprintln :: proc(args: ..any) -> string {
|
||||
buf := make_string_dynamic_buffer();
|
||||
const aprintln = proc(args: ..any) -> string {
|
||||
var buf = make_string_dynamic_buffer();
|
||||
sbprintln(&buf, ..args);
|
||||
return to_string(buf);
|
||||
}
|
||||
aprintf :: proc(fmt: string, args: ..any) -> string {
|
||||
buf := make_string_dynamic_buffer();
|
||||
const aprintf = proc(fmt: string, args: ..any) -> string {
|
||||
var buf = make_string_dynamic_buffer();
|
||||
sbprintf(&buf, fmt, ..args);
|
||||
return to_string(buf);
|
||||
}
|
||||
@@ -162,16 +162,16 @@ aprintf :: proc(fmt: string, args: ..any) -> string {
|
||||
|
||||
// bprint* procedures return a string that was allocated with the current context
|
||||
// They must be freed accordingly
|
||||
bprint :: proc(buf: []u8, args: ..any) -> string {
|
||||
sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
|
||||
const bprint = proc(buf: []u8, args: ..any) -> string {
|
||||
var sb = make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
|
||||
return sbprint(&sb, ..args);
|
||||
}
|
||||
bprintln :: proc(buf: []u8, args: ..any) -> string {
|
||||
sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
|
||||
const bprintln = proc(buf: []u8, args: ..any) -> string {
|
||||
var sb = make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
|
||||
return sbprintln(&sb, ..args);
|
||||
}
|
||||
bprintf :: proc(buf: []u8, fmt: string, args: ..any) -> string {
|
||||
sb := make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
|
||||
const bprintf = proc(buf: []u8, fmt: string, args: ..any) -> string {
|
||||
var sb = make_string_buffer_from_slice(buf[0..<0..<len(buf)]);
|
||||
return sbprintf(&sb, fmt, ..args);
|
||||
}
|
||||
|
||||
@@ -180,14 +180,14 @@ bprintf :: proc(buf: []u8, fmt: string, args: ..any) -> string {
|
||||
|
||||
|
||||
|
||||
fprint_type :: proc(fd: os.Handle, info: ^TypeInfo) {
|
||||
data: [_BUFFER_SIZE]u8;
|
||||
buf := make_string_buffer_from_slice(data[0..<0]);
|
||||
const fprint_type = proc(fd: os.Handle, info: ^TypeInfo) {
|
||||
var data: [_BUFFER_SIZE]u8;
|
||||
var buf = make_string_buffer_from_slice(data[0..<0]);
|
||||
write_type(&buf, info);
|
||||
os.write(fd, string_buffer_data(buf));
|
||||
}
|
||||
|
||||
write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
const write_type = proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
if ti == nil {
|
||||
return;
|
||||
}
|
||||
@@ -238,11 +238,11 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
if info.params == nil {
|
||||
write_string(buf, "()");
|
||||
} else {
|
||||
t := info.params.(^Tuple);
|
||||
var t = info.params.(^Tuple);
|
||||
write_string(buf, "(");
|
||||
for type, i in t.types {
|
||||
for t, i in t.types {
|
||||
if i > 0 { write_string(buf, ", "); }
|
||||
write_type(buf, type);
|
||||
write_type(buf, t);
|
||||
}
|
||||
write_string(buf, ")");
|
||||
}
|
||||
@@ -251,24 +251,24 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
write_type(buf, info.results);
|
||||
}
|
||||
case Tuple:
|
||||
count := len(info.names);
|
||||
var count = len(info.names);
|
||||
if count != 1 { write_string(buf, "("); }
|
||||
for name, i in info.names {
|
||||
if i > 0 { write_string(buf, ", "); }
|
||||
|
||||
type := info.types[i];
|
||||
var t = info.types[i];
|
||||
|
||||
if len(name) > 0 {
|
||||
write_string(buf, name);
|
||||
write_string(buf, ": ");
|
||||
}
|
||||
write_type(buf, type);
|
||||
write_type(buf, t);
|
||||
}
|
||||
if count != 1 { write_string(buf, ")"); }
|
||||
|
||||
case Array:
|
||||
write_string(buf, "[");
|
||||
fi := FmtInfo{buf = buf};
|
||||
var fi = FmtInfo{buf = buf};
|
||||
write_int(buf, i64(info.count), 10);
|
||||
write_string(buf, "]");
|
||||
write_type(buf, info.elem);
|
||||
@@ -312,8 +312,8 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
|
||||
case Union:
|
||||
write_string(buf, "union {");
|
||||
cf := info.common_fields;
|
||||
total_count := 0;
|
||||
var cf = info.common_fields;
|
||||
var total_count = 0;
|
||||
for name, i in cf.names {
|
||||
if i > 0 {
|
||||
write_string(buf, ", ");
|
||||
@@ -331,15 +331,15 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
write_byte(buf, '{');
|
||||
defer write_byte(buf, '}');
|
||||
|
||||
variant_type := type_info_base(info.variant_types[i]);
|
||||
variant := variant_type.(^Struct);
|
||||
var variant_type = type_info_base(info.variant_types[i]);
|
||||
var variant = variant_type.(^Struct);
|
||||
|
||||
vc := len(variant.names)-len(cf.names);
|
||||
var vc = len(variant.names)-len(cf.names);
|
||||
for j in 0..vc {
|
||||
if j > 0 {
|
||||
write_string(buf, ", ");
|
||||
}
|
||||
index := j + len(cf.names);
|
||||
var index = j + len(cf.names);
|
||||
write_string(buf, variant.names[index]);
|
||||
write_string(buf, ": ");
|
||||
write_type(buf, variant.types[index]);
|
||||
@@ -392,17 +392,17 @@ write_type :: proc(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||
}
|
||||
|
||||
|
||||
_parse_int :: proc(s: string, offset: int) -> (result: int, offset: int, ok: bool) {
|
||||
is_digit :: proc(r: rune) -> bool #inline {
|
||||
const _parse_int = proc(s: string, offset: int) -> (result: int, offset: int, ok: bool) {
|
||||
const is_digit = proc(r: rune) -> bool #inline {
|
||||
return '0' <= r && r <= '9';
|
||||
}
|
||||
|
||||
result := 0;
|
||||
ok := true;
|
||||
var result = 0;
|
||||
var ok = true;
|
||||
|
||||
i := 0;
|
||||
var i = 0;
|
||||
for i < len(s[offset..]) {
|
||||
c := rune(s[offset+i]);
|
||||
var c = rune(s[offset+i]);
|
||||
if !is_digit(c) {
|
||||
break;
|
||||
}
|
||||
@@ -415,15 +415,15 @@ _parse_int :: proc(s: string, offset: int) -> (result: int, offset: int, ok: boo
|
||||
return result, offset+i, i != 0;
|
||||
}
|
||||
|
||||
_arg_number :: proc(fi: ^FmtInfo, arg_index: int, format: string, offset, arg_count: int) -> (index, offset: int, ok: bool) {
|
||||
parse_arg_number :: proc(format: string) -> (int, int, bool) {
|
||||
const _arg_number = proc(fi: ^FmtInfo, arg_index: int, format: string, offset, arg_count: int) -> (index, offset: int, ok: bool) {
|
||||
const parse_arg_number = proc(format: string) -> (int, int, bool) {
|
||||
if len(format) < 3 {
|
||||
return 0, 1, false;
|
||||
}
|
||||
|
||||
for i in 1..len(format) {
|
||||
if format[i] == ']' {
|
||||
width, new_index, ok := _parse_int(format, 1);
|
||||
var width, new_index, ok = _parse_int(format, 1);
|
||||
if !ok || new_index != i {
|
||||
return 0, i+1, false;
|
||||
}
|
||||
@@ -439,7 +439,7 @@ _arg_number :: proc(fi: ^FmtInfo, arg_index: int, format: string, offset, arg_co
|
||||
return arg_index, offset, false;
|
||||
}
|
||||
fi.reordered = true;
|
||||
index, width, ok := parse_arg_number(format[offset..]);
|
||||
var index, width, ok = parse_arg_number(format[offset..]);
|
||||
if ok && 0 <= index && index < arg_count {
|
||||
return index, offset+width, true;
|
||||
}
|
||||
@@ -447,12 +447,12 @@ _arg_number :: proc(fi: ^FmtInfo, arg_index: int, format: string, offset, arg_co
|
||||
return arg_index, offset+width, false;
|
||||
}
|
||||
|
||||
int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
|
||||
num := 0;
|
||||
new_arg_index := arg_index;
|
||||
ok := true;
|
||||
const int_from_arg = proc(args: []any, arg_index: int) -> (int, int, bool) {
|
||||
var num = 0;
|
||||
var new_arg_index = arg_index;
|
||||
var ok = true;
|
||||
if arg_index < len(args) {
|
||||
arg := args[arg_index];
|
||||
var arg = args[arg_index];
|
||||
arg.type_info = type_info_base(arg.type_info);
|
||||
match i in arg {
|
||||
case int: num = i;
|
||||
@@ -473,7 +473,7 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
|
||||
}
|
||||
|
||||
|
||||
fmt_bad_verb :: proc(using fi: ^FmtInfo, verb: rune) {
|
||||
const fmt_bad_verb = proc(using fi: ^FmtInfo, verb: rune) {
|
||||
assert(verb != 'v');
|
||||
write_string(buf, "%!");
|
||||
write_rune(buf, verb);
|
||||
@@ -488,7 +488,7 @@ fmt_bad_verb :: proc(using fi: ^FmtInfo, verb: rune) {
|
||||
write_byte(buf, ')');
|
||||
}
|
||||
|
||||
fmt_bool :: proc(using fi: ^FmtInfo, b: bool, verb: rune) {
|
||||
const fmt_bool = proc(using fi: ^FmtInfo, b: bool, verb: rune) {
|
||||
match verb {
|
||||
case 't', 'v':
|
||||
write_string(buf, b ? "true" : "false");
|
||||
@@ -498,39 +498,39 @@ fmt_bool :: proc(using fi: ^FmtInfo, b: bool, verb: rune) {
|
||||
}
|
||||
|
||||
|
||||
fmt_write_padding :: proc(fi: ^FmtInfo, width: int) {
|
||||
const fmt_write_padding = proc(fi: ^FmtInfo, width: int) {
|
||||
if width <= 0 {
|
||||
return;
|
||||
}
|
||||
pad_byte: u8 = '0';
|
||||
var pad_byte: u8 = '0';
|
||||
if fi.space {
|
||||
pad_byte = ' ';
|
||||
}
|
||||
|
||||
data := string_buffer_data(fi.buf^);
|
||||
count := min(width, cap(data)-len(data));
|
||||
var data = string_buffer_data(fi.buf^);
|
||||
var count = min(width, cap(data)-len(data));
|
||||
for _ in 0..<count {
|
||||
write_byte(fi.buf, pad_byte);
|
||||
}
|
||||
}
|
||||
|
||||
_fmt_int :: proc(fi: ^FmtInfo, u: u128, base: int, is_signed: bool, bit_size: int, digits: string) {
|
||||
_, neg := strconv.is_integer_negative(u128(u), is_signed, bit_size);
|
||||
const _fmt_int = proc(fi: ^FmtInfo, u: u128, base: int, is_signed: bool, bit_size: int, digits: string) {
|
||||
var _, neg = strconv.is_integer_negative(u128(u), is_signed, bit_size);
|
||||
|
||||
BUF_SIZE :: 256;
|
||||
const BUF_SIZE = 256;
|
||||
if fi.width_set || fi.prec_set {
|
||||
width := fi.width + fi.prec + 3; // 3 extra bytes for sign and prefix
|
||||
var width = fi.width + fi.prec + 3; // 3 extra bytes for sign and prefix
|
||||
if width > BUF_SIZE {
|
||||
// TODO(bill):????
|
||||
panic("_fmt_int: buffer overrun. Width and precision too big");
|
||||
}
|
||||
}
|
||||
|
||||
prec := 0;
|
||||
var prec = 0;
|
||||
if fi.prec_set {
|
||||
prec = fi.prec;
|
||||
if prec == 0 && u == 0 {
|
||||
prev_zero := fi.zero;
|
||||
var prev_zero = fi.zero;
|
||||
fi.zero = false;
|
||||
fmt_write_padding(fi, fi.width);
|
||||
fi.zero = prev_zero;
|
||||
@@ -551,18 +551,18 @@ _fmt_int :: proc(fi: ^FmtInfo, u: u128, base: int, is_signed: bool, bit_size: in
|
||||
panic("_fmt_int: unknown base, whoops");
|
||||
}
|
||||
|
||||
buf: [256]u8;
|
||||
start := 0;
|
||||
var buf: [256]u8;
|
||||
var start = 0;
|
||||
|
||||
|
||||
flags: strconv.IntFlag;
|
||||
var flags: strconv.IntFlag;
|
||||
if fi.hash && !fi.zero { flags |= strconv.IntFlag.Prefix; }
|
||||
if fi.plus { flags |= strconv.IntFlag.Plus; }
|
||||
if fi.space { flags |= strconv.IntFlag.Space; }
|
||||
s := strconv.append_bits(buf[start..<start], u128(u), base, is_signed, bit_size, digits, flags);
|
||||
var s = strconv.append_bits(buf[start..<start], u128(u), base, is_signed, bit_size, digits, flags);
|
||||
|
||||
if fi.hash && fi.zero {
|
||||
c: u8;
|
||||
var c: u8;
|
||||
match base {
|
||||
case 2: c = 'b';
|
||||
case 8: c = 'o';
|
||||
@@ -576,16 +576,16 @@ _fmt_int :: proc(fi: ^FmtInfo, u: u128, base: int, is_signed: bool, bit_size: in
|
||||
}
|
||||
}
|
||||
|
||||
prev_zero := fi.zero;
|
||||
var prev_zero = fi.zero;
|
||||
defer fi.zero = prev_zero;
|
||||
fi.zero = false;
|
||||
_pad(fi, s);
|
||||
}
|
||||
|
||||
immutable __DIGITS_LOWER := "0123456789abcdefx";
|
||||
immutable __DIGITS_UPPER := "0123456789ABCDEFX";
|
||||
immutable var __DIGITS_LOWER = "0123456789abcdefx";
|
||||
immutable var __DIGITS_UPPER = "0123456789ABCDEFX";
|
||||
|
||||
fmt_rune :: proc(fi: ^FmtInfo, r: rune, verb: rune) {
|
||||
const fmt_rune = proc(fi: ^FmtInfo, r: rune, verb: rune) {
|
||||
match verb {
|
||||
case 'c', 'r', 'v':
|
||||
write_rune(fi.buf, r);
|
||||
@@ -594,7 +594,7 @@ fmt_rune :: proc(fi: ^FmtInfo, r: rune, verb: rune) {
|
||||
}
|
||||
}
|
||||
|
||||
fmt_int :: proc(fi: ^FmtInfo, u: u128, is_signed: bool, bit_size: int, verb: rune) {
|
||||
const fmt_int = proc(fi: ^FmtInfo, u: u128, is_signed: bool, bit_size: int, verb: rune) {
|
||||
match verb {
|
||||
case 'v': _fmt_int(fi, u, 10, is_signed, bit_size, __DIGITS_LOWER);
|
||||
case 'b': _fmt_int(fi, u, 2, is_signed, bit_size, __DIGITS_LOWER);
|
||||
@@ -605,7 +605,7 @@ fmt_int :: proc(fi: ^FmtInfo, u: u128, is_signed: bool, bit_size: int, verb: run
|
||||
case 'c', 'r':
|
||||
fmt_rune(fi, rune(u), verb);
|
||||
case 'U':
|
||||
r := rune(u);
|
||||
var r = rune(u);
|
||||
if r < 0 || r > utf8.MAX_RUNE {
|
||||
fmt_bad_verb(fi, verb);
|
||||
} else {
|
||||
@@ -618,12 +618,12 @@ fmt_int :: proc(fi: ^FmtInfo, u: u128, is_signed: bool, bit_size: int, verb: run
|
||||
}
|
||||
}
|
||||
|
||||
_pad :: proc(fi: ^FmtInfo, s: string) {
|
||||
const _pad = proc(fi: ^FmtInfo, s: string) {
|
||||
if !fi.width_set {
|
||||
write_string(fi.buf, s);
|
||||
return;
|
||||
}
|
||||
width := fi.width - utf8.rune_count(s);
|
||||
var width = fi.width - utf8.rune_count(s);
|
||||
if fi.minus { // right pad
|
||||
write_string(fi.buf, s);
|
||||
fmt_write_padding(fi, width);
|
||||
@@ -633,19 +633,19 @@ _pad :: proc(fi: ^FmtInfo, s: string) {
|
||||
}
|
||||
}
|
||||
|
||||
fmt_float :: proc(fi: ^FmtInfo, v: f64, bit_size: int, verb: rune) {
|
||||
const fmt_float = proc(fi: ^FmtInfo, v: f64, bit_size: int, verb: rune) {
|
||||
match verb {
|
||||
// case 'e', 'E', 'f', 'F', 'g', 'G', 'v':
|
||||
// case 'f', 'F', 'v':
|
||||
|
||||
case 'f', 'F', 'v':
|
||||
prec: int = 3;
|
||||
var prec: int = 3;
|
||||
var buf: [386]u8;
|
||||
if fi.prec_set {
|
||||
prec = fi.prec;
|
||||
}
|
||||
|
||||
buf: [386]u8;
|
||||
str := strconv.append_float(buf[1..<1], v, 'f', prec, bit_size);
|
||||
var str = strconv.append_float(buf[1..<1], v, 'f', prec, bit_size);
|
||||
str = string(buf[0..len(str)]);
|
||||
if str[1] == '+' || str[1] == '-' {
|
||||
str = str[1..];
|
||||
@@ -678,13 +678,13 @@ fmt_float :: proc(fi: ^FmtInfo, v: f64, bit_size: int, verb: rune) {
|
||||
fmt_bad_verb(fi, verb);
|
||||
}
|
||||
}
|
||||
fmt_string :: proc(fi: ^FmtInfo, s: string, verb: rune) {
|
||||
const fmt_string = proc(fi: ^FmtInfo, s: string, verb: rune) {
|
||||
match verb {
|
||||
case 's', 'v':
|
||||
write_string(fi.buf, s);
|
||||
|
||||
case 'x', 'X':
|
||||
space := fi.space;
|
||||
var space = fi.space;
|
||||
fi.space = false;
|
||||
defer fi.space = space;
|
||||
|
||||
@@ -700,7 +700,7 @@ fmt_string :: proc(fi: ^FmtInfo, s: string, verb: rune) {
|
||||
}
|
||||
}
|
||||
|
||||
fmt_pointer :: proc(fi: ^FmtInfo, p: rawptr, verb: rune) {
|
||||
const fmt_pointer = proc(fi: ^FmtInfo, p: rawptr, verb: rune) {
|
||||
match verb {
|
||||
case 'p', 'v':
|
||||
// Okay
|
||||
@@ -708,14 +708,14 @@ fmt_pointer :: proc(fi: ^FmtInfo, p: rawptr, verb: rune) {
|
||||
fmt_bad_verb(fi, verb);
|
||||
return;
|
||||
}
|
||||
u := u128(uint(p));
|
||||
var u = u128(uint(p));
|
||||
if !fi.hash || verb == 'v' {
|
||||
write_string(fi.buf, "0x");
|
||||
}
|
||||
_fmt_int(fi, u, 16, false, 8*size_of(rawptr), __DIGITS_UPPER);
|
||||
}
|
||||
|
||||
fmt_enum :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
const fmt_enum = proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
if v.type_info == nil || v.data == nil {
|
||||
write_string(fi.buf, "<nil>");
|
||||
return;
|
||||
@@ -731,10 +731,10 @@ fmt_enum :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
case 'd', 'f':
|
||||
fmt_arg(fi, any{v.data, type_info_base(e.base)}, verb);
|
||||
case 's', 'v':
|
||||
i: i128;
|
||||
f: f64;
|
||||
ok := false;
|
||||
a := any{v.data, type_info_base(e.base)};
|
||||
var i: i128;
|
||||
var f: f64;
|
||||
var ok = false;
|
||||
var a = any{v.data, type_info_base(e.base)};
|
||||
match v in a {
|
||||
case rune: i = i128(v);
|
||||
case i8: i = i128(v);
|
||||
@@ -786,7 +786,7 @@ fmt_enum :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
}
|
||||
|
||||
|
||||
fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
const fmt_value = proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
if v.data == nil || v.type_info == nil {
|
||||
write_string(fi.buf, "<nil>");
|
||||
return;
|
||||
@@ -809,7 +809,7 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
}
|
||||
write_string(fi.buf, b.names[i]);
|
||||
write_string(fi.buf, " = ");
|
||||
data := ^u8(v.data) + b.offsets[i];
|
||||
var data = ^u8(v.data) + b.offsets[i];
|
||||
fmt_arg(fi, any{rawptr(data), b.types[i]}, 'v');
|
||||
}
|
||||
write_byte(fi.buf, '}');
|
||||
@@ -842,31 +842,31 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
if i > 0 {
|
||||
write_string(fi.buf, ", ");
|
||||
}
|
||||
data := ^u8(v.data) + i*info.elem_size;
|
||||
var data = ^u8(v.data) + i*info.elem_size;
|
||||
fmt_arg(fi, any{rawptr(data), info.elem}, verb);
|
||||
}
|
||||
|
||||
case DynamicArray:
|
||||
write_byte(fi.buf, '[');
|
||||
defer write_byte(fi.buf, ']');
|
||||
array := ^raw.DynamicArray(v.data);
|
||||
var array = ^raw.DynamicArray(v.data);
|
||||
for i in 0..<array.len {
|
||||
if i > 0 {
|
||||
write_string(fi.buf, ", ");
|
||||
}
|
||||
data := ^u8(array.data) + i*info.elem_size;
|
||||
var data = ^u8(array.data) + i*info.elem_size;
|
||||
fmt_arg(fi, any{rawptr(data), info.elem}, verb);
|
||||
}
|
||||
|
||||
case Slice:
|
||||
write_byte(fi.buf, '[');
|
||||
defer write_byte(fi.buf, ']');
|
||||
slice := ^[]u8(v.data);
|
||||
var slice = ^[]u8(v.data);
|
||||
for _, i in slice {
|
||||
if i > 0 {
|
||||
write_string(fi.buf, ", ");
|
||||
}
|
||||
data := &slice[0] + i*info.elem_size;
|
||||
var data = &slice[0] + i*info.elem_size;
|
||||
fmt_arg(fi, any{rawptr(data), info.elem}, verb);
|
||||
}
|
||||
|
||||
@@ -879,7 +879,7 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
write_string(fi.buf, ", ");
|
||||
}
|
||||
|
||||
data := ^u8(v.data) + i*info.elem_size;
|
||||
var data = ^u8(v.data) + i*info.elem_size;
|
||||
fmt_value(fi, any{rawptr(data), info.elem}, verb);
|
||||
}
|
||||
|
||||
@@ -891,29 +891,29 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
|
||||
write_string(fi.buf, "map[");
|
||||
defer write_byte(fi.buf, ']');
|
||||
entries := &(^raw.DynamicMap(v.data).entries);
|
||||
gs := type_info_base(info.generated_struct).(^Struct);
|
||||
ed := type_info_base(gs.types[1]).(^DynamicArray);
|
||||
var entries = &(^raw.DynamicMap(v.data).entries);
|
||||
var gs = type_info_base(info.generated_struct).(^Struct);
|
||||
var ed = type_info_base(gs.types[1]).(^DynamicArray);
|
||||
|
||||
entry_type := ed.elem.(^Struct);
|
||||
entry_size := ed.elem_size;
|
||||
var entry_type = ed.elem.(^Struct);
|
||||
var entry_size = ed.elem_size;
|
||||
for i in 0..<entries.len {
|
||||
if i > 0 {
|
||||
write_string(fi.buf, ", ");
|
||||
}
|
||||
data := ^u8(entries.data) + i*entry_size;
|
||||
var data = ^u8(entries.data) + i*entry_size;
|
||||
|
||||
header := ^__MapEntryHeader(data);
|
||||
var header = ^__MapEntryHeader(data);
|
||||
if types.is_string(info.key) {
|
||||
write_string(fi.buf, header.key.str);
|
||||
} else {
|
||||
fi := FmtInfo{buf = fi.buf};
|
||||
var fi = FmtInfo{buf = fi.buf};
|
||||
fmt_arg(&fi, any{rawptr(&header.key.hash), info.key}, 'v');
|
||||
}
|
||||
|
||||
write_string(fi.buf, "=");
|
||||
|
||||
value := data + entry_type.offsets[2];
|
||||
var value = data + entry_type.offsets[2];
|
||||
fmt_arg(fi, any{rawptr(value), info.value}, 'v');
|
||||
}
|
||||
|
||||
@@ -929,7 +929,7 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
}
|
||||
write_string(fi.buf, info.names[i]);
|
||||
write_string(fi.buf, " = ");
|
||||
data := ^u8(v.data) + info.offsets[i];
|
||||
var data = ^u8(v.data) + info.offsets[i];
|
||||
fmt_value(fi, any{rawptr(data), info.types[i]}, 'v');
|
||||
}
|
||||
|
||||
@@ -937,7 +937,7 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
write_byte(fi.buf, '{');
|
||||
defer write_byte(fi.buf, '}');
|
||||
|
||||
cf := info.common_fields;
|
||||
var cf = info.common_fields;
|
||||
|
||||
for _, i in cf.names {
|
||||
if i > 0 {
|
||||
@@ -945,7 +945,7 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
}
|
||||
write_string(fi.buf, cf.names[i]);
|
||||
write_string(fi.buf, " = ");
|
||||
data := ^u8(v.data) + cf.offsets[i];
|
||||
var data = ^u8(v.data) + cf.offsets[i];
|
||||
fmt_value(fi, any{rawptr(data), cf.types[i]}, 'v');
|
||||
}
|
||||
|
||||
@@ -962,11 +962,11 @@ fmt_value :: proc(fi: ^FmtInfo, v: any, verb: rune) {
|
||||
}
|
||||
}
|
||||
|
||||
fmt_complex :: proc(fi: ^FmtInfo, c: complex128, bits: int, verb: rune) {
|
||||
const fmt_complex = proc(fi: ^FmtInfo, c: complex128, bits: int, verb: rune) {
|
||||
match verb {
|
||||
case 'f', 'F', 'v':
|
||||
r := real(c);
|
||||
i := imag(c);
|
||||
var r = real(c);
|
||||
var i = imag(c);
|
||||
fmt_float(fi, r, bits/2, verb);
|
||||
if !fi.plus && i >= 0 {
|
||||
write_rune(fi.buf, '+');
|
||||
@@ -980,15 +980,15 @@ fmt_complex :: proc(fi: ^FmtInfo, c: complex128, bits: int, verb: rune) {
|
||||
}
|
||||
}
|
||||
|
||||
_u128_to_lo_hi :: proc(a: u128) -> (lo, hi: u64) { return u64(a), u64(a>>64); }
|
||||
_i128_to_lo_hi :: proc(a: u128) -> (lo: u64 hi: i64) { return u64(a), i64(a>>64); }
|
||||
const _u128_to_lo_hi = proc(a: u128) -> (lo, hi: u64) { return u64(a), u64(a>>64); }
|
||||
const _i128_to_lo_hi = proc(a: u128) -> (lo: u64 hi: i64) { return u64(a), i64(a>>64); }
|
||||
|
||||
|
||||
do_foo :: proc(fi: ^FmtInfo, f: f64) {
|
||||
const do_foo = proc(fi: ^FmtInfo, f: f64) {
|
||||
fmt_string(fi, "Hellope$%!", 'v');
|
||||
}
|
||||
|
||||
fmt_arg :: proc(fi: ^FmtInfo, arg: any, verb: rune) {
|
||||
const fmt_arg = proc(fi: ^FmtInfo, arg: any, verb: rune) {
|
||||
if arg == nil {
|
||||
write_string(fi.buf, "<nil>");
|
||||
return;
|
||||
@@ -996,7 +996,7 @@ fmt_arg :: proc(fi: ^FmtInfo, arg: any, verb: rune) {
|
||||
fi.arg = arg;
|
||||
|
||||
if verb == 'T' {
|
||||
ti := arg.type_info;
|
||||
var ti = arg.type_info;
|
||||
match a in arg {
|
||||
case ^TypeInfo: ti = a;
|
||||
}
|
||||
@@ -1005,7 +1005,7 @@ fmt_arg :: proc(fi: ^FmtInfo, arg: any, verb: rune) {
|
||||
}
|
||||
|
||||
|
||||
base_arg := arg;
|
||||
var base_arg = arg;
|
||||
base_arg.type_info = type_info_base(base_arg.type_info);
|
||||
match a in base_arg {
|
||||
case any: fmt_arg(fi, a, verb);
|
||||
@@ -1043,13 +1043,13 @@ fmt_arg :: proc(fi: ^FmtInfo, arg: any, verb: rune) {
|
||||
|
||||
|
||||
|
||||
sbprint :: proc(buf: ^StringBuffer, args: ..any) -> string {
|
||||
fi: FmtInfo;
|
||||
const sbprint = proc(buf: ^StringBuffer, args: ..any) -> string {
|
||||
var fi: FmtInfo;
|
||||
fi.buf = buf;
|
||||
|
||||
prev_string := false;
|
||||
var prev_string = false;
|
||||
for arg, i in args {
|
||||
is_string := arg != nil && types.is_string(arg.type_info);
|
||||
var is_string = arg != nil && types.is_string(arg.type_info);
|
||||
if i > 0 && !is_string && !prev_string {
|
||||
write_byte(buf, ' ');
|
||||
}
|
||||
@@ -1059,8 +1059,8 @@ sbprint :: proc(buf: ^StringBuffer, args: ..any) -> string {
|
||||
return to_string(buf^);
|
||||
}
|
||||
|
||||
sbprintln :: proc(buf: ^StringBuffer, args: ..any) -> string {
|
||||
fi: FmtInfo;
|
||||
const sbprintln = proc(buf: ^StringBuffer, args: ..any) -> string {
|
||||
var fi: FmtInfo;
|
||||
fi.buf = buf;
|
||||
|
||||
for arg, i in args {
|
||||
@@ -1073,15 +1073,15 @@ sbprintln :: proc(buf: ^StringBuffer, args: ..any) -> string {
|
||||
return to_string(buf^);
|
||||
}
|
||||
|
||||
sbprintf :: proc(b: ^StringBuffer, fmt: string, args: ..any) -> string {
|
||||
fi := FmtInfo{};
|
||||
end := len(fmt);
|
||||
arg_index := 0;
|
||||
was_prev_index := false;
|
||||
for i := 0; i < end; /**/ {
|
||||
const sbprintf = proc(b: ^StringBuffer, fmt: string, args: ..any) -> string {
|
||||
var fi = FmtInfo{};
|
||||
var end = len(fmt);
|
||||
var arg_index = 0;
|
||||
var was_prev_index = false;
|
||||
for var i = 0; i < end; /**/ {
|
||||
fi = FmtInfo{buf = b, good_arg_index = true};
|
||||
|
||||
prev_i := i;
|
||||
var prev_i = i;
|
||||
for i < end && fmt[i] != '%' {
|
||||
i++;
|
||||
}
|
||||
@@ -1173,7 +1173,7 @@ sbprintf :: proc(b: ^StringBuffer, fmt: string, args: ..any) -> string {
|
||||
break;
|
||||
}
|
||||
|
||||
verb, w := utf8.decode_rune(fmt[i..]);
|
||||
var verb, w = utf8.decode_rune(fmt[i..]);
|
||||
i += w;
|
||||
|
||||
if verb == '%' {
|
||||
|
||||
292
core/math.odin
292
core/math.odin
@@ -1,100 +1,100 @@
|
||||
TAU :: 6.28318530717958647692528676655900576;
|
||||
PI :: 3.14159265358979323846264338327950288;
|
||||
ONE_OVER_TAU :: 0.636619772367581343075535053490057448;
|
||||
ONE_OVER_PI :: 0.159154943091895335768883763372514362;
|
||||
const TAU = 6.28318530717958647692528676655900576;
|
||||
const PI = 3.14159265358979323846264338327950288;
|
||||
const ONE_OVER_TAU = 0.636619772367581343075535053490057448;
|
||||
const ONE_OVER_PI = 0.159154943091895335768883763372514362;
|
||||
|
||||
E :: 2.71828182845904523536;
|
||||
SQRT_TWO :: 1.41421356237309504880168872420969808;
|
||||
SQRT_THREE :: 1.73205080756887729352744634150587236;
|
||||
SQRT_FIVE :: 2.23606797749978969640917366873127623;
|
||||
const E = 2.71828182845904523536;
|
||||
const SQRT_TWO = 1.41421356237309504880168872420969808;
|
||||
const SQRT_THREE = 1.73205080756887729352744634150587236;
|
||||
const SQRT_FIVE = 2.23606797749978969640917366873127623;
|
||||
|
||||
LOG_TWO :: 0.693147180559945309417232121458176568;
|
||||
LOG_TEN :: 2.30258509299404568401799145468436421;
|
||||
const LOG_TWO = 0.693147180559945309417232121458176568;
|
||||
const LOG_TEN = 2.30258509299404568401799145468436421;
|
||||
|
||||
EPSILON :: 1.19209290e-7;
|
||||
const EPSILON = 1.19209290e-7;
|
||||
|
||||
τ :: TAU;
|
||||
π :: PI;
|
||||
const τ = TAU;
|
||||
const π = PI;
|
||||
|
||||
Vec2 :: [vector 2]f32;
|
||||
Vec3 :: [vector 3]f32;
|
||||
Vec4 :: [vector 4]f32;
|
||||
const Vec2 = [vector 2]f32;
|
||||
const Vec3 = [vector 3]f32;
|
||||
const Vec4 = [vector 4]f32;
|
||||
|
||||
// Column major
|
||||
Mat2 :: [2][2]f32;
|
||||
Mat3 :: [3][3]f32;
|
||||
Mat4 :: [4][4]f32;
|
||||
const Mat2 = [2][2]f32;
|
||||
const Mat3 = [3][3]f32;
|
||||
const Mat4 = [4][4]f32;
|
||||
|
||||
Complex :: complex64;
|
||||
const Complex = complex64;
|
||||
|
||||
sqrt :: proc(x: f32) -> f32 #foreign __llvm_core "llvm.sqrt.f32";
|
||||
sqrt :: proc(x: f64) -> f64 #foreign __llvm_core "llvm.sqrt.f64";
|
||||
const sqrt = proc(x: f32) -> f32 #foreign __llvm_core "llvm.sqrt.f32";
|
||||
const sqrt = proc(x: f64) -> f64 #foreign __llvm_core "llvm.sqrt.f64";
|
||||
|
||||
sin :: proc(θ: f32) -> f32 #foreign __llvm_core "llvm.sin.f32";
|
||||
sin :: proc(θ: f64) -> f64 #foreign __llvm_core "llvm.sin.f64";
|
||||
const sin = proc(θ: f32) -> f32 #foreign __llvm_core "llvm.sin.f32";
|
||||
const sin = proc(θ: f64) -> f64 #foreign __llvm_core "llvm.sin.f64";
|
||||
|
||||
cos :: proc(θ: f32) -> f32 #foreign __llvm_core "llvm.cos.f32";
|
||||
cos :: proc(θ: f64) -> f64 #foreign __llvm_core "llvm.cos.f64";
|
||||
const cos = proc(θ: f32) -> f32 #foreign __llvm_core "llvm.cos.f32";
|
||||
const cos = proc(θ: f64) -> f64 #foreign __llvm_core "llvm.cos.f64";
|
||||
|
||||
tan :: proc(θ: f32) -> f32 #inline { return sin(θ)/cos(θ); }
|
||||
tan :: proc(θ: f64) -> f64 #inline { return sin(θ)/cos(θ); }
|
||||
const tan = proc(θ: f32) -> f32 #inline { return sin(θ)/cos(θ); }
|
||||
const tan = proc(θ: f64) -> f64 #inline { return sin(θ)/cos(θ); }
|
||||
|
||||
pow :: proc(x, power: f32) -> f32 #foreign __llvm_core "llvm.pow.f32";
|
||||
pow :: proc(x, power: f64) -> f64 #foreign __llvm_core "llvm.pow.f64";
|
||||
const pow = proc(x, power: f32) -> f32 #foreign __llvm_core "llvm.pow.f32";
|
||||
const pow = proc(x, power: f64) -> f64 #foreign __llvm_core "llvm.pow.f64";
|
||||
|
||||
|
||||
lerp :: proc(a, b, t: f32) -> (x: f32) { return a*(1-t) + b*t; }
|
||||
lerp :: proc(a, b, t: f64) -> (x: f64) { return a*(1-t) + b*t; }
|
||||
unlerp :: proc(a, b, x: f32) -> (t: f32) { return (x-a)/(b-a); }
|
||||
unlerp :: proc(a, b, x: f64) -> (t: f64) { return (x-a)/(b-a); }
|
||||
const lerp = proc(a, b, t: f32) -> (x: f32) { return a*(1-t) + b*t; }
|
||||
const lerp = proc(a, b, t: f64) -> (x: f64) { return a*(1-t) + b*t; }
|
||||
const unlerp = proc(a, b, x: f32) -> (t: f32) { return (x-a)/(b-a); }
|
||||
const unlerp = proc(a, b, x: f64) -> (t: f64) { return (x-a)/(b-a); }
|
||||
|
||||
|
||||
sign :: proc(x: f32) -> f32 { return x >= 0 ? +1 : -1; }
|
||||
sign :: proc(x: f64) -> f64 { return x >= 0 ? +1 : -1; }
|
||||
const sign = proc(x: f32) -> f32 { return x >= 0 ? +1 : -1; }
|
||||
const sign = proc(x: f64) -> f64 { return x >= 0 ? +1 : -1; }
|
||||
|
||||
fmuladd :: proc(a, b, c: f32) -> f32 #foreign __llvm_core "llvm.fmuladd.f32";
|
||||
fmuladd :: proc(a, b, c: f64) -> f64 #foreign __llvm_core "llvm.fmuladd.f64";
|
||||
const fmuladd = proc(a, b, c: f32) -> f32 #foreign __llvm_core "llvm.fmuladd.f32";
|
||||
const fmuladd = proc(a, b, c: f64) -> f64 #foreign __llvm_core "llvm.fmuladd.f64";
|
||||
|
||||
|
||||
copy_sign :: proc(x, y: f32) -> f32 {
|
||||
ix := transmute(u32, x);
|
||||
iy := transmute(u32, y);
|
||||
const copy_sign = proc(x, y: f32) -> f32 {
|
||||
var ix = transmute(u32, x);
|
||||
var iy = transmute(u32, y);
|
||||
ix &= 0x7fff_ffff;
|
||||
ix |= iy & 0x8000_0000;
|
||||
return transmute(f32, ix);
|
||||
}
|
||||
|
||||
copy_sign :: proc(x, y: f64) -> f64 {
|
||||
ix := transmute(u64, x);
|
||||
iy := transmute(u64, y);
|
||||
const copy_sign = proc(x, y: f64) -> f64 {
|
||||
var ix = transmute(u64, x);
|
||||
var iy = transmute(u64, y);
|
||||
ix &= 0x7fff_ffff_ffff_ff;
|
||||
ix |= iy & 0x8000_0000_0000_0000;
|
||||
return transmute(f64, ix);
|
||||
}
|
||||
|
||||
round :: proc(x: f32) -> f32 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
|
||||
round :: proc(x: f64) -> f64 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
|
||||
const round = proc(x: f32) -> f32 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
|
||||
const round = proc(x: f64) -> f64 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
|
||||
|
||||
floor :: proc(x: f32) -> f32 { return x >= 0 ? f32(i64(x)) : f32(i64(x-0.5)); } // TODO: Get accurate versions
|
||||
floor :: proc(x: f64) -> f64 { return x >= 0 ? f64(i64(x)) : f64(i64(x-0.5)); } // TODO: Get accurate versions
|
||||
const floor = proc(x: f32) -> f32 { return x >= 0 ? f32(i64(x)) : f32(i64(x-0.5)); } // TODO: Get accurate versions
|
||||
const floor = proc(x: f64) -> f64 { return x >= 0 ? f64(i64(x)) : f64(i64(x-0.5)); } // TODO: Get accurate versions
|
||||
|
||||
ceil :: proc(x: f32) -> f32 { return x < 0 ? f32(i64(x)) : f32(i64(x+1)); } // TODO: Get accurate versions
|
||||
ceil :: proc(x: f64) -> f64 { return x < 0 ? f64(i64(x)) : f64(i64(x+1)); } // TODO: Get accurate versions
|
||||
const ceil = proc(x: f32) -> f32 { return x < 0 ? f32(i64(x)) : f32(i64(x+1)); } // TODO: Get accurate versions
|
||||
const ceil = proc(x: f64) -> f64 { return x < 0 ? f64(i64(x)) : f64(i64(x+1)); } // TODO: Get accurate versions
|
||||
|
||||
remainder :: proc(x, y: f32) -> f32 { return x - round(x/y) * y; }
|
||||
remainder :: proc(x, y: f64) -> f64 { return x - round(x/y) * y; }
|
||||
const remainder = proc(x, y: f32) -> f32 { return x - round(x/y) * y; }
|
||||
const remainder = proc(x, y: f64) -> f64 { return x - round(x/y) * y; }
|
||||
|
||||
mod :: proc(x, y: f32) -> f32 {
|
||||
const mod = proc(x, y: f32) -> f32 {
|
||||
y = abs(y);
|
||||
result := remainder(abs(x), y);
|
||||
var result = remainder(abs(x), y);
|
||||
if sign(result) < 0 {
|
||||
result += y;
|
||||
}
|
||||
return copy_sign(result, x);
|
||||
}
|
||||
mod :: proc(x, y: f64) -> f64 {
|
||||
const mod = proc(x, y: f64) -> f64 {
|
||||
y = abs(y);
|
||||
result := remainder(abs(x), y);
|
||||
var result = remainder(abs(x), y);
|
||||
if sign(result) < 0 {
|
||||
result += y;
|
||||
}
|
||||
@@ -102,48 +102,48 @@ mod :: proc(x, y: f64) -> f64 {
|
||||
}
|
||||
|
||||
|
||||
to_radians :: proc(degrees: f32) -> f32 { return degrees * TAU / 360; }
|
||||
to_degrees :: proc(radians: f32) -> f32 { return radians * 360 / TAU; }
|
||||
const to_radians = proc(degrees: f32) -> f32 { return degrees * TAU / 360; }
|
||||
const to_degrees = proc(radians: f32) -> f32 { return radians * 360 / TAU; }
|
||||
|
||||
|
||||
|
||||
dot :: proc(a, b: Vec2) -> f32 { c := a*b; return c.x + c.y; }
|
||||
dot :: proc(a, b: Vec3) -> f32 { c := a*b; return c.x + c.y + c.z; }
|
||||
dot :: proc(a, b: Vec4) -> f32 { c := a*b; return c.x + c.y + c.z + c.w; }
|
||||
const dot = proc(a, b: Vec2) -> f32 { var c = a*b; return c.x + c.y; }
|
||||
const dot = proc(a, b: Vec3) -> f32 { var c = a*b; return c.x + c.y + c.z; }
|
||||
const dot = proc(a, b: Vec4) -> f32 { var c = a*b; return c.x + c.y + c.z + c.w; }
|
||||
|
||||
cross :: proc(x, y: Vec3) -> Vec3 {
|
||||
a := swizzle(x, 1, 2, 0) * swizzle(y, 2, 0, 1);
|
||||
b := swizzle(x, 2, 0, 1) * swizzle(y, 1, 2, 0);
|
||||
const cross = proc(x, y: Vec3) -> Vec3 {
|
||||
var a = swizzle(x, 1, 2, 0) * swizzle(y, 2, 0, 1);
|
||||
var b = swizzle(x, 2, 0, 1) * swizzle(y, 1, 2, 0);
|
||||
return a - b;
|
||||
}
|
||||
|
||||
|
||||
mag :: proc(v: Vec2) -> f32 { return sqrt(dot(v, v)); }
|
||||
mag :: proc(v: Vec3) -> f32 { return sqrt(dot(v, v)); }
|
||||
mag :: proc(v: Vec4) -> f32 { return sqrt(dot(v, v)); }
|
||||
const mag = proc(v: Vec2) -> f32 { return sqrt(dot(v, v)); }
|
||||
const mag = proc(v: Vec3) -> f32 { return sqrt(dot(v, v)); }
|
||||
const mag = proc(v: Vec4) -> f32 { return sqrt(dot(v, v)); }
|
||||
|
||||
norm :: proc(v: Vec2) -> Vec2 { return v / mag(v); }
|
||||
norm :: proc(v: Vec3) -> Vec3 { return v / mag(v); }
|
||||
norm :: proc(v: Vec4) -> Vec4 { return v / mag(v); }
|
||||
const norm = proc(v: Vec2) -> Vec2 { return v / mag(v); }
|
||||
const norm = proc(v: Vec3) -> Vec3 { return v / mag(v); }
|
||||
const norm = proc(v: Vec4) -> Vec4 { return v / mag(v); }
|
||||
|
||||
norm0 :: proc(v: Vec2) -> Vec2 {
|
||||
m := mag(v);
|
||||
const norm0 = proc(v: Vec2) -> Vec2 {
|
||||
var m = mag(v);
|
||||
if m == 0 {
|
||||
return 0;
|
||||
}
|
||||
return v / m;
|
||||
}
|
||||
|
||||
norm0 :: proc(v: Vec3) -> Vec3 {
|
||||
m := mag(v);
|
||||
const norm0 = proc(v: Vec3) -> Vec3 {
|
||||
var m = mag(v);
|
||||
if m == 0 {
|
||||
return 0;
|
||||
}
|
||||
return v / m;
|
||||
}
|
||||
|
||||
norm0 :: proc(v: Vec4) -> Vec4 {
|
||||
m := mag(v);
|
||||
const norm0 = proc(v: Vec4) -> Vec4 {
|
||||
var m = mag(v);
|
||||
if m == 0 {
|
||||
return 0;
|
||||
}
|
||||
@@ -152,7 +152,7 @@ norm0 :: proc(v: Vec4) -> Vec4 {
|
||||
|
||||
|
||||
|
||||
mat4_identity :: proc() -> Mat4 {
|
||||
const mat4_identity = proc() -> Mat4 {
|
||||
return Mat4{
|
||||
{1, 0, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
@@ -161,7 +161,7 @@ mat4_identity :: proc() -> Mat4 {
|
||||
};
|
||||
}
|
||||
|
||||
mat4_transpose :: proc(m: Mat4) -> Mat4 {
|
||||
const mat4_transpose = proc(m: Mat4) -> Mat4 {
|
||||
for j in 0..<4 {
|
||||
for i in 0..<4 {
|
||||
m[i][j], m[j][i] = m[j][i], m[i][j];
|
||||
@@ -170,8 +170,8 @@ mat4_transpose :: proc(m: Mat4) -> Mat4 {
|
||||
return m;
|
||||
}
|
||||
|
||||
mul :: proc(a, b: Mat4) -> Mat4 {
|
||||
c: Mat4;
|
||||
const mul = proc(a, b: Mat4) -> Mat4 {
|
||||
var c: Mat4;
|
||||
for j in 0..<4 {
|
||||
for i in 0..<4 {
|
||||
c[j][i] = a[0][i]*b[j][0] +
|
||||
@@ -183,7 +183,7 @@ mul :: proc(a, b: Mat4) -> Mat4 {
|
||||
return c;
|
||||
}
|
||||
|
||||
mul :: proc(m: Mat4, v: Vec4) -> Vec4 {
|
||||
const mul = proc(m: Mat4, v: Vec4) -> Vec4 {
|
||||
return Vec4{
|
||||
m[0][0]*v.x + m[1][0]*v.y + m[2][0]*v.z + m[3][0]*v.w,
|
||||
m[0][1]*v.x + m[1][1]*v.y + m[2][1]*v.z + m[3][1]*v.w,
|
||||
@@ -192,28 +192,28 @@ mul :: proc(m: Mat4, v: Vec4) -> Vec4 {
|
||||
};
|
||||
}
|
||||
|
||||
inverse :: proc(m: Mat4) -> Mat4 {
|
||||
o: Mat4;
|
||||
const inverse = proc(m: Mat4) -> Mat4 {
|
||||
var o: Mat4;
|
||||
|
||||
sf00 := m[2][2] * m[3][3] - m[3][2] * m[2][3];
|
||||
sf01 := m[2][1] * m[3][3] - m[3][1] * m[2][3];
|
||||
sf02 := m[2][1] * m[3][2] - m[3][1] * m[2][2];
|
||||
sf03 := m[2][0] * m[3][3] - m[3][0] * m[2][3];
|
||||
sf04 := m[2][0] * m[3][2] - m[3][0] * m[2][2];
|
||||
sf05 := m[2][0] * m[3][1] - m[3][0] * m[2][1];
|
||||
sf06 := m[1][2] * m[3][3] - m[3][2] * m[1][3];
|
||||
sf07 := m[1][1] * m[3][3] - m[3][1] * m[1][3];
|
||||
sf08 := m[1][1] * m[3][2] - m[3][1] * m[1][2];
|
||||
sf09 := m[1][0] * m[3][3] - m[3][0] * m[1][3];
|
||||
sf10 := m[1][0] * m[3][2] - m[3][0] * m[1][2];
|
||||
sf11 := m[1][1] * m[3][3] - m[3][1] * m[1][3];
|
||||
sf12 := m[1][0] * m[3][1] - m[3][0] * m[1][1];
|
||||
sf13 := m[1][2] * m[2][3] - m[2][2] * m[1][3];
|
||||
sf14 := m[1][1] * m[2][3] - m[2][1] * m[1][3];
|
||||
sf15 := m[1][1] * m[2][2] - m[2][1] * m[1][2];
|
||||
sf16 := m[1][0] * m[2][3] - m[2][0] * m[1][3];
|
||||
sf17 := m[1][0] * m[2][2] - m[2][0] * m[1][2];
|
||||
sf18 := m[1][0] * m[2][1] - m[2][0] * m[1][1];
|
||||
var sf00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
|
||||
var sf01 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
|
||||
var sf02 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
|
||||
var sf03 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
|
||||
var sf04 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
|
||||
var sf05 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
|
||||
var sf06 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
|
||||
var sf07 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
|
||||
var sf08 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
|
||||
var sf09 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
|
||||
var sf10 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
|
||||
var sf11 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
|
||||
var sf12 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
|
||||
var sf13 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
|
||||
var sf14 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
|
||||
var sf15 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
|
||||
var sf16 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
|
||||
var sf17 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
|
||||
var sf18 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
|
||||
|
||||
o[0][0] = +(m[1][1] * sf00 - m[1][2] * sf01 + m[1][3] * sf02);
|
||||
o[0][1] = -(m[1][0] * sf00 - m[1][2] * sf03 + m[1][3] * sf04);
|
||||
@@ -235,7 +235,7 @@ inverse :: proc(m: Mat4) -> Mat4 {
|
||||
o[3][2] = -(m[0][0] * sf14 - m[0][1] * sf16 + m[0][3] * sf18);
|
||||
o[3][3] = +(m[0][0] * sf15 - m[0][1] * sf17 + m[0][2] * sf18);
|
||||
|
||||
ood := 1.0 / (m[0][0] * o[0][0] +
|
||||
var ood = 1.0 / (m[0][0] * o[0][0] +
|
||||
m[0][1] * o[0][1] +
|
||||
m[0][2] * o[0][2] +
|
||||
m[0][3] * o[0][3]);
|
||||
@@ -261,8 +261,8 @@ inverse :: proc(m: Mat4) -> Mat4 {
|
||||
}
|
||||
|
||||
|
||||
mat4_translate :: proc(v: Vec3) -> Mat4 {
|
||||
m := mat4_identity();
|
||||
const mat4_translate = proc(v: Vec3) -> Mat4 {
|
||||
var m = mat4_identity();
|
||||
m[3][0] = v.x;
|
||||
m[3][1] = v.y;
|
||||
m[3][2] = v.z;
|
||||
@@ -270,14 +270,14 @@ mat4_translate :: proc(v: Vec3) -> Mat4 {
|
||||
return m;
|
||||
}
|
||||
|
||||
mat4_rotate :: proc(v: Vec3, angle_radians: f32) -> Mat4 {
|
||||
c := cos(angle_radians);
|
||||
s := sin(angle_radians);
|
||||
const mat4_rotate = proc(v: Vec3, angle_radians: f32) -> Mat4 {
|
||||
var c = cos(angle_radians);
|
||||
var s = sin(angle_radians);
|
||||
|
||||
a := norm(v);
|
||||
t := a * (1-c);
|
||||
var a = norm(v);
|
||||
var t = a * (1-c);
|
||||
|
||||
rot := mat4_identity();
|
||||
var rot = mat4_identity();
|
||||
|
||||
rot[0][0] = c + t.x*a.x;
|
||||
rot[0][1] = 0 + t.x*a.y + s*a.z;
|
||||
@@ -297,14 +297,14 @@ mat4_rotate :: proc(v: Vec3, angle_radians: f32) -> Mat4 {
|
||||
return rot;
|
||||
}
|
||||
|
||||
scale :: proc(m: Mat4, v: Vec3) -> Mat4 {
|
||||
const scale = proc(m: Mat4, v: Vec3) -> Mat4 {
|
||||
m[0][0] *= v.x;
|
||||
m[1][1] *= v.y;
|
||||
m[2][2] *= v.z;
|
||||
return m;
|
||||
}
|
||||
|
||||
scale :: proc(m: Mat4, s: f32) -> Mat4 {
|
||||
const scale = proc(m: Mat4, s: f32) -> Mat4 {
|
||||
m[0][0] *= s;
|
||||
m[1][1] *= s;
|
||||
m[2][2] *= s;
|
||||
@@ -312,10 +312,10 @@ scale :: proc(m: Mat4, s: f32) -> Mat4 {
|
||||
}
|
||||
|
||||
|
||||
look_at :: proc(eye, centre, up: Vec3) -> Mat4 {
|
||||
f := norm(centre - eye);
|
||||
s := norm(cross(f, up));
|
||||
u := cross(s, f);
|
||||
const look_at = proc(eye, centre, up: Vec3) -> Mat4 {
|
||||
var f = norm(centre - eye);
|
||||
var s = norm(cross(f, up));
|
||||
var u = cross(s, f);
|
||||
|
||||
return Mat4{
|
||||
{+s.x, +u.x, -f.x, 0},
|
||||
@@ -325,9 +325,9 @@ look_at :: proc(eye, centre, up: Vec3) -> Mat4 {
|
||||
};
|
||||
}
|
||||
|
||||
perspective :: proc(fovy, aspect, near, far: f32) -> Mat4 {
|
||||
m: Mat4;
|
||||
tan_half_fovy := tan(0.5 * fovy);
|
||||
const perspective = proc(fovy, aspect, near, far: f32) -> Mat4 {
|
||||
var m: Mat4;
|
||||
var tan_half_fovy = tan(0.5 * fovy);
|
||||
m[0][0] = 1.0 / (aspect*tan_half_fovy);
|
||||
m[1][1] = 1.0 / (tan_half_fovy);
|
||||
m[2][2] = -(far + near) / (far - near);
|
||||
@@ -337,8 +337,8 @@ perspective :: proc(fovy, aspect, near, far: f32) -> Mat4 {
|
||||
}
|
||||
|
||||
|
||||
ortho3d :: proc(left, right, bottom, top, near, far: f32) -> Mat4 {
|
||||
m := mat4_identity();
|
||||
const ortho3d = proc(left, right, bottom, top, near, far: f32) -> Mat4 {
|
||||
var m = mat4_identity();
|
||||
m[0][0] = +2.0 / (right - left);
|
||||
m[1][1] = +2.0 / (top - bottom);
|
||||
m[2][2] = -2.0 / (far - near);
|
||||
@@ -352,28 +352,28 @@ ortho3d :: proc(left, right, bottom, top, near, far: f32) -> Mat4 {
|
||||
|
||||
|
||||
|
||||
F32_DIG :: 6;
|
||||
F32_EPSILON :: 1.192092896e-07;
|
||||
F32_GUARD :: 0;
|
||||
F32_MANT_DIG :: 24;
|
||||
F32_MAX :: 3.402823466e+38;
|
||||
F32_MAX_10_EXP :: 38;
|
||||
F32_MAX_EXP :: 128;
|
||||
F32_MIN :: 1.175494351e-38;
|
||||
F32_MIN_10_EXP :: -37;
|
||||
F32_MIN_EXP :: -125;
|
||||
F32_NORMALIZE :: 0;
|
||||
F32_RADIX :: 2;
|
||||
F32_ROUNDS :: 1;
|
||||
const F32_DIG = 6;
|
||||
const F32_EPSILON = 1.192092896e-07;
|
||||
const F32_GUARD = 0;
|
||||
const F32_MANT_DIG = 24;
|
||||
const F32_MAX = 3.402823466e+38;
|
||||
const F32_MAX_10_EXP = 38;
|
||||
const F32_MAX_EXP = 128;
|
||||
const F32_MIN = 1.175494351e-38;
|
||||
const F32_MIN_10_EXP = -37;
|
||||
const F32_MIN_EXP = -125;
|
||||
const F32_NORMALIZE = 0;
|
||||
const F32_RADIX = 2;
|
||||
const F32_ROUNDS = 1;
|
||||
|
||||
F64_DIG :: 15; // # of decimal digits of precision
|
||||
F64_EPSILON :: 2.2204460492503131e-016; // smallest such that 1.0+F64_EPSILON != 1.0
|
||||
F64_MANT_DIG :: 53; // # of bits in mantissa
|
||||
F64_MAX :: 1.7976931348623158e+308; // max value
|
||||
F64_MAX_10_EXP :: 308; // max decimal exponent
|
||||
F64_MAX_EXP :: 1024; // max binary exponent
|
||||
F64_MIN :: 2.2250738585072014e-308; // min positive value
|
||||
F64_MIN_10_EXP :: -307; // min decimal exponent
|
||||
F64_MIN_EXP :: -1021; // min binary exponent
|
||||
F64_RADIX :: 2; // exponent radix
|
||||
F64_ROUNDS :: 1; // addition rounding: near
|
||||
const F64_DIG = 15; // # of decimal digits of precision
|
||||
const F64_EPSILON = 2.2204460492503131e-016; // smallest such that 1.0+F64_EPSILON != 1.0
|
||||
const F64_MANT_DIG = 53; // # of bits in mantissa
|
||||
const F64_MAX = 1.7976931348623158e+308; // max value
|
||||
const F64_MAX_10_EXP = 308; // max decimal exponent
|
||||
const F64_MAX_EXP = 1024; // max binary exponent
|
||||
const F64_MIN = 2.2250738585072014e-308; // min positive value
|
||||
const F64_MIN_10_EXP = -307; // min decimal exponent
|
||||
const F64_MIN_EXP = -1021; // min binary exponent
|
||||
const F64_RADIX = 2; // exponent radix
|
||||
const F64_ROUNDS = 1; // addition rounding: near
|
||||
|
||||
112
core/mem.odin
112
core/mem.odin
@@ -1,47 +1,47 @@
|
||||
#import "fmt.odin";
|
||||
#import "os.odin";
|
||||
|
||||
swap :: proc(b: u16) -> u16 #foreign __llvm_core "llvm.bswap.i16";
|
||||
swap :: proc(b: u32) -> u32 #foreign __llvm_core "llvm.bswap.i32";
|
||||
swap :: proc(b: u64) -> u64 #foreign __llvm_core "llvm.bswap.i64";
|
||||
const swap = proc(b: u16) -> u16 #foreign __llvm_core "llvm.bswap.i16";
|
||||
const swap = proc(b: u32) -> u32 #foreign __llvm_core "llvm.bswap.i32";
|
||||
const swap = proc(b: u64) -> u64 #foreign __llvm_core "llvm.bswap.i64";
|
||||
|
||||
|
||||
set :: proc(data: rawptr, value: i32, len: int) -> rawptr {
|
||||
const set = proc(data: rawptr, value: i32, len: int) -> rawptr {
|
||||
return __mem_set(data, value, len);
|
||||
}
|
||||
zero :: proc(data: rawptr, len: int) -> rawptr {
|
||||
const zero = proc(data: rawptr, len: int) -> rawptr {
|
||||
return __mem_zero(data, len);
|
||||
}
|
||||
copy :: proc(dst, src: rawptr, len: int) -> rawptr {
|
||||
const copy = proc(dst, src: rawptr, len: int) -> rawptr {
|
||||
return __mem_copy(dst, src, len);
|
||||
}
|
||||
copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr {
|
||||
const copy_non_overlapping = proc(dst, src: rawptr, len: int) -> rawptr {
|
||||
return __mem_copy_non_overlapping(dst, src, len);
|
||||
}
|
||||
compare :: proc(a, b: []u8) -> int {
|
||||
const compare = proc(a, b: []u8) -> int {
|
||||
return __mem_compare(&a[0], &b[0], min(len(a), len(b)));
|
||||
}
|
||||
|
||||
|
||||
|
||||
kilobytes :: proc(x: int) -> int #inline { return (x) * 1024; }
|
||||
megabytes :: proc(x: int) -> int #inline { return kilobytes(x) * 1024; }
|
||||
gigabytes :: proc(x: int) -> int #inline { return megabytes(x) * 1024; }
|
||||
terabytes :: proc(x: int) -> int #inline { return gigabytes(x) * 1024; }
|
||||
const kilobytes = proc(x: int) -> int #inline { return (x) * 1024; }
|
||||
const megabytes = proc(x: int) -> int #inline { return kilobytes(x) * 1024; }
|
||||
const gigabytes = proc(x: int) -> int #inline { return megabytes(x) * 1024; }
|
||||
const terabytes = proc(x: int) -> int #inline { return gigabytes(x) * 1024; }
|
||||
|
||||
is_power_of_two :: proc(x: int) -> bool {
|
||||
const is_power_of_two = proc(x: int) -> bool {
|
||||
if x <= 0 {
|
||||
return false;
|
||||
}
|
||||
return (x & (x-1)) == 0;
|
||||
}
|
||||
|
||||
align_forward :: proc(ptr: rawptr, align: int) -> rawptr {
|
||||
const align_forward = proc(ptr: rawptr, align: int) -> rawptr {
|
||||
assert(is_power_of_two(align));
|
||||
|
||||
a := uint(align);
|
||||
p := uint(ptr);
|
||||
modulo := p & (a-1);
|
||||
var a = uint(align);
|
||||
var p = uint(ptr);
|
||||
var modulo = p & (a-1);
|
||||
if modulo != 0 {
|
||||
p += a - modulo;
|
||||
}
|
||||
@@ -50,23 +50,23 @@ align_forward :: proc(ptr: rawptr, align: int) -> rawptr {
|
||||
|
||||
|
||||
|
||||
AllocationHeader :: struct {
|
||||
const AllocationHeader = struct {
|
||||
size: int,
|
||||
}
|
||||
|
||||
allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: int) {
|
||||
const allocation_header_fill = proc(header: ^AllocationHeader, data: rawptr, size: int) {
|
||||
header.size = size;
|
||||
ptr := ^int(header+1);
|
||||
var ptr = ^int(header+1);
|
||||
|
||||
for i := 0; rawptr(ptr) < data; i++ {
|
||||
for var i = 0; rawptr(ptr) < data; i++ {
|
||||
(ptr+i)^ = -1;
|
||||
}
|
||||
}
|
||||
allocation_header :: proc(data: rawptr) -> ^AllocationHeader {
|
||||
const allocation_header = proc(data: rawptr) -> ^AllocationHeader {
|
||||
if data == nil {
|
||||
return nil;
|
||||
}
|
||||
p := ^int(data);
|
||||
var p = ^int(data);
|
||||
for (p-1)^ == -1 {
|
||||
p = (p-1);
|
||||
}
|
||||
@@ -78,14 +78,14 @@ allocation_header :: proc(data: rawptr) -> ^AllocationHeader {
|
||||
|
||||
|
||||
// Custom allocators
|
||||
Arena :: struct {
|
||||
const Arena = struct {
|
||||
backing: Allocator,
|
||||
offset: int,
|
||||
memory: []u8,
|
||||
temp_count: int,
|
||||
}
|
||||
|
||||
ArenaTempMemory :: struct {
|
||||
const ArenaTempMemory = struct {
|
||||
arena: ^Arena,
|
||||
original_count: int,
|
||||
}
|
||||
@@ -94,19 +94,19 @@ ArenaTempMemory :: struct {
|
||||
|
||||
|
||||
|
||||
init_arena_from_memory :: proc(using a: ^Arena, data: []u8) {
|
||||
const init_arena_from_memory = proc(using a: ^Arena, data: []u8) {
|
||||
backing = Allocator{};
|
||||
memory = data[0..<0];
|
||||
temp_count = 0;
|
||||
}
|
||||
|
||||
init_arena_from_context :: proc(using a: ^Arena, size: int) {
|
||||
const init_arena_from_context = proc(using a: ^Arena, size: int) {
|
||||
backing = context.allocator;
|
||||
memory = make([]u8, size);
|
||||
temp_count = 0;
|
||||
}
|
||||
|
||||
free_arena :: proc(using a: ^Arena) {
|
||||
const free_arena = proc(using a: ^Arena) {
|
||||
if backing.procedure != nil {
|
||||
push_allocator backing {
|
||||
free(memory);
|
||||
@@ -116,31 +116,31 @@ free_arena :: proc(using a: ^Arena) {
|
||||
}
|
||||
}
|
||||
|
||||
arena_allocator :: proc(arena: ^Arena) -> Allocator {
|
||||
const arena_allocator = proc(arena: ^Arena) -> Allocator {
|
||||
return Allocator{
|
||||
procedure = arena_allocator_proc,
|
||||
data = arena,
|
||||
};
|
||||
}
|
||||
|
||||
arena_allocator_proc :: proc(allocator_data: rawptr, mode: AllocatorMode,
|
||||
const arena_allocator_proc = proc(allocator_data: rawptr, mode: AllocatorMode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
||||
using AllocatorMode;
|
||||
arena := ^Arena(allocator_data);
|
||||
var arena = ^Arena(allocator_data);
|
||||
|
||||
match mode {
|
||||
case Alloc:
|
||||
total_size := size + alignment;
|
||||
var total_size = size + alignment;
|
||||
|
||||
if arena.offset + total_size > len(arena.memory) {
|
||||
fmt.fprintln(os.stderr, "Arena out of memory");
|
||||
return nil;
|
||||
}
|
||||
|
||||
#no_bounds_check end := &arena.memory[arena.offset];
|
||||
#no_bounds_check var end = &arena.memory[arena.offset];
|
||||
|
||||
ptr := align_forward(end, alignment);
|
||||
var ptr = align_forward(end, alignment);
|
||||
arena.offset += total_size;
|
||||
return zero(ptr, size);
|
||||
|
||||
@@ -158,15 +158,15 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: AllocatorMode,
|
||||
return nil;
|
||||
}
|
||||
|
||||
begin_arena_temp_memory :: proc(a: ^Arena) -> ArenaTempMemory {
|
||||
tmp: ArenaTempMemory;
|
||||
const begin_arena_temp_memory = proc(a: ^Arena) -> ArenaTempMemory {
|
||||
var tmp: ArenaTempMemory;
|
||||
tmp.arena = a;
|
||||
tmp.original_count = len(a.memory);
|
||||
a.temp_count++;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
end_arena_temp_memory :: proc(using tmp: ArenaTempMemory) {
|
||||
const end_arena_temp_memory = proc(using tmp: ArenaTempMemory) {
|
||||
assert(len(arena.memory) >= original_count);
|
||||
assert(arena.temp_count > 0);
|
||||
arena.memory = arena.memory[0..<original_count];
|
||||
@@ -179,8 +179,8 @@ end_arena_temp_memory :: proc(using tmp: ArenaTempMemory) {
|
||||
|
||||
|
||||
|
||||
align_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
||||
prev_pow2 :: proc(n: i64) -> i64 {
|
||||
const align_of_type_info = proc(type_info: ^TypeInfo) -> int {
|
||||
const prev_pow2 = proc(n: i64) -> i64 {
|
||||
if n <= 0 {
|
||||
return 0;
|
||||
}
|
||||
@@ -193,8 +193,8 @@ align_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
||||
return n - (n >> 1);
|
||||
}
|
||||
|
||||
WORD_SIZE :: size_of(int);
|
||||
MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
|
||||
const WORD_SIZE = size_of(int);
|
||||
const MAX_ALIGN = size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
|
||||
using TypeInfo;
|
||||
match info in type_info {
|
||||
case Named:
|
||||
@@ -220,9 +220,9 @@ align_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
||||
case Slice:
|
||||
return WORD_SIZE;
|
||||
case Vector:
|
||||
size := size_of_type_info(info.elem);
|
||||
count := int(max(prev_pow2(i64(info.count)), 1));
|
||||
total := size * count;
|
||||
var size = size_of_type_info(info.elem);
|
||||
var count = int(max(prev_pow2(i64(info.count)), 1));
|
||||
var total = size * count;
|
||||
return clamp(total, 1, MAX_ALIGN);
|
||||
case Tuple:
|
||||
return info.align;
|
||||
@@ -241,13 +241,13 @@ align_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
||||
return 0;
|
||||
}
|
||||
|
||||
align_formula :: proc(size, align: int) -> int {
|
||||
result := size + align-1;
|
||||
const align_formula = proc(size, align: int) -> int {
|
||||
var result = size + align-1;
|
||||
return result - result%align;
|
||||
}
|
||||
|
||||
size_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
||||
WORD_SIZE :: size_of(int);
|
||||
const size_of_type_info = proc(type_info: ^TypeInfo) -> int {
|
||||
const WORD_SIZE = size_of(int);
|
||||
using TypeInfo;
|
||||
match info in type_info {
|
||||
case Named:
|
||||
@@ -267,26 +267,26 @@ size_of_type_info :: proc(type_info: ^TypeInfo) -> int {
|
||||
case Procedure:
|
||||
return WORD_SIZE;
|
||||
case Array:
|
||||
count := info.count;
|
||||
var count = info.count;
|
||||
if count == 0 {
|
||||
return 0;
|
||||
}
|
||||
size := size_of_type_info(info.elem);
|
||||
align := align_of_type_info(info.elem);
|
||||
alignment := align_formula(size, align);
|
||||
var size = size_of_type_info(info.elem);
|
||||
var align = align_of_type_info(info.elem);
|
||||
var alignment = align_formula(size, align);
|
||||
return alignment*(count-1) + size;
|
||||
case DynamicArray:
|
||||
return size_of(rawptr) + 2*size_of(int) + size_of(Allocator);
|
||||
case Slice:
|
||||
return 2*WORD_SIZE;
|
||||
case Vector:
|
||||
count := info.count;
|
||||
var count = info.count;
|
||||
if count == 0 {
|
||||
return 0;
|
||||
}
|
||||
size := size_of_type_info(info.elem);
|
||||
align := align_of_type_info(info.elem);
|
||||
alignment := align_formula(size, align);
|
||||
var size = size_of_type_info(info.elem);
|
||||
var align = align_of_type_info(info.elem);
|
||||
var alignment = align_formula(size, align);
|
||||
return alignment*(count-1) + size;
|
||||
case Struct:
|
||||
return info.size;
|
||||
|
||||
158
core/opengl.odin
158
core/opengl.odin
@@ -4,113 +4,113 @@
|
||||
#import "sys/wgl.odin" when ODIN_OS == "windows";
|
||||
#load "opengl_constants.odin";
|
||||
|
||||
Clear :: proc(mask: u32) #foreign lib "glClear";
|
||||
ClearColor :: proc(r, g, b, a: f32) #foreign lib "glClearColor";
|
||||
Begin :: proc(mode: i32) #foreign lib "glBegin";
|
||||
End :: proc() #foreign lib "glEnd";
|
||||
Finish :: proc() #foreign lib "glFinish";
|
||||
BlendFunc :: proc(sfactor, dfactor: i32) #foreign lib "glBlendFunc";
|
||||
Enable :: proc(cap: i32) #foreign lib "glEnable";
|
||||
Disable :: proc(cap: i32) #foreign lib "glDisable";
|
||||
GenTextures :: proc(count: i32, result: ^u32) #foreign lib "glGenTextures";
|
||||
DeleteTextures:: proc(count: i32, result: ^u32) #foreign lib "glDeleteTextures";
|
||||
TexParameteri :: proc(target, pname, param: i32) #foreign lib "glTexParameteri";
|
||||
TexParameterf :: proc(target: i32, pname: i32, param: f32) #foreign lib "glTexParameterf";
|
||||
BindTexture :: proc(target: i32, texture: u32) #foreign lib "glBindTexture";
|
||||
LoadIdentity :: proc() #foreign lib "glLoadIdentity";
|
||||
Viewport :: proc(x, y, width, height: i32) #foreign lib "glViewport";
|
||||
Ortho :: proc(left, right, bottom, top, near, far: f64) #foreign lib "glOrtho";
|
||||
Color3f :: proc(r, g, b: f32) #foreign lib "glColor3f";
|
||||
Vertex3f :: proc(x, y, z: f32) #foreign lib "glVertex3f";
|
||||
GetError :: proc() -> i32 #foreign lib "glGetError";
|
||||
GetString :: proc(name: i32) -> ^u8 #foreign lib "glGetString";
|
||||
GetIntegerv :: proc(name: i32, v: ^i32) #foreign lib "glGetIntegerv";
|
||||
TexCoord2f :: proc(x, y: f32) #foreign lib "glTexCoord2f";
|
||||
TexImage2D :: proc(target, level, internal_format,
|
||||
const Clear = proc(mask: u32) #foreign lib "glClear";
|
||||
const ClearColor = proc(r, g, b, a: f32) #foreign lib "glClearColor";
|
||||
const Begin = proc(mode: i32) #foreign lib "glBegin";
|
||||
const End = proc() #foreign lib "glEnd";
|
||||
const Finish = proc() #foreign lib "glFinish";
|
||||
const BlendFunc = proc(sfactor, dfactor: i32) #foreign lib "glBlendFunc";
|
||||
const Enable = proc(cap: i32) #foreign lib "glEnable";
|
||||
const Disable = proc(cap: i32) #foreign lib "glDisable";
|
||||
const GenTextures = proc(count: i32, result: ^u32) #foreign lib "glGenTextures";
|
||||
const DeleteTextures= proc(count: i32, result: ^u32) #foreign lib "glDeleteTextures";
|
||||
const TexParameteri = proc(target, pname, param: i32) #foreign lib "glTexParameteri";
|
||||
const TexParameterf = proc(target: i32, pname: i32, param: f32) #foreign lib "glTexParameterf";
|
||||
const BindTexture = proc(target: i32, texture: u32) #foreign lib "glBindTexture";
|
||||
const LoadIdentity = proc() #foreign lib "glLoadIdentity";
|
||||
const Viewport = proc(x, y, width, height: i32) #foreign lib "glViewport";
|
||||
const Ortho = proc(left, right, bottom, top, near, far: f64) #foreign lib "glOrtho";
|
||||
const Color3f = proc(r, g, b: f32) #foreign lib "glColor3f";
|
||||
const Vertex3f = proc(x, y, z: f32) #foreign lib "glVertex3f";
|
||||
const GetError = proc() -> i32 #foreign lib "glGetError";
|
||||
const GetString = proc(name: i32) -> ^u8 #foreign lib "glGetString";
|
||||
const GetIntegerv = proc(name: i32, v: ^i32) #foreign lib "glGetIntegerv";
|
||||
const TexCoord2f = proc(x, y: f32) #foreign lib "glTexCoord2f";
|
||||
const TexImage2D = proc(target, level, internal_format,
|
||||
width, height, border,
|
||||
format, type: i32, pixels: rawptr) #foreign lib "glTexImage2D";
|
||||
format, type_: i32, pixels: rawptr) #foreign lib "glTexImage2D";
|
||||
|
||||
|
||||
_string_data :: proc(s: string) -> ^u8 #inline { return &s[0]; }
|
||||
const _string_data = proc(s: string) -> ^u8 #inline { return &s[0]; }
|
||||
|
||||
_libgl := win32.load_library_a(_string_data("opengl32.dll\x00"));
|
||||
var _libgl = win32.load_library_a(_string_data("opengl32.dll\x00"));
|
||||
|
||||
get_proc_address :: proc(name: string) -> proc() #cc_c {
|
||||
const get_proc_address = proc(name: string) -> proc() #cc_c {
|
||||
if name[len(name)-1] == 0 {
|
||||
name = name[0..<len(name)-1];
|
||||
}
|
||||
// NOTE(bill): null terminated
|
||||
assert((&name[0] + len(name))^ == 0);
|
||||
res := wgl.get_proc_address(&name[0]);
|
||||
var res = wgl.get_proc_address(&name[0]);
|
||||
if res == nil {
|
||||
res = win32.get_proc_address(_libgl, &name[0]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
GenBuffers: proc(count: i32, buffers: ^u32) #cc_c;
|
||||
GenVertexArrays: proc(count: i32, buffers: ^u32) #cc_c;
|
||||
GenSamplers: proc(count: i32, buffers: ^u32) #cc_c;
|
||||
DeleteBuffers: proc(count: i32, buffers: ^u32) #cc_c;
|
||||
BindBuffer: proc(target: i32, buffer: u32) #cc_c;
|
||||
BindVertexArray: proc(buffer: u32) #cc_c;
|
||||
DeleteVertexArrays: proc(count: i32, arrays: ^u32) #cc_c;
|
||||
BindSampler: proc(position: i32, sampler: u32) #cc_c;
|
||||
BufferData: proc(target: i32, size: int, data: rawptr, usage: i32) #cc_c;
|
||||
BufferSubData: proc(target: i32, offset, size: int, data: rawptr) #cc_c;
|
||||
var GenBuffers: proc(count: i32, buffers: ^u32) #cc_c;
|
||||
var GenVertexArrays: proc(count: i32, buffers: ^u32) #cc_c;
|
||||
var GenSamplers: proc(count: i32, buffers: ^u32) #cc_c;
|
||||
var DeleteBuffers: proc(count: i32, buffers: ^u32) #cc_c;
|
||||
var BindBuffer: proc(target: i32, buffer: u32) #cc_c;
|
||||
var BindVertexArray: proc(buffer: u32) #cc_c;
|
||||
var DeleteVertexArrays: proc(count: i32, arrays: ^u32) #cc_c;
|
||||
var BindSampler: proc(position: i32, sampler: u32) #cc_c;
|
||||
var BufferData: proc(target: i32, size: int, data: rawptr, usage: i32) #cc_c;
|
||||
var BufferSubData: proc(target: i32, offset, size: int, data: rawptr) #cc_c;
|
||||
|
||||
DrawArrays: proc(mode, first: i32, count: u32) #cc_c;
|
||||
DrawElements: proc(mode: i32, count: u32, type_: i32, indices: rawptr) #cc_c;
|
||||
var DrawArrays: proc(mode, first: i32, count: u32) #cc_c;
|
||||
var DrawElements: proc(mode: i32, count: u32, type_: i32, indices: rawptr) #cc_c;
|
||||
|
||||
MapBuffer: proc(target, access: i32) -> rawptr #cc_c;
|
||||
UnmapBuffer: proc(target: i32) #cc_c;
|
||||
var MapBuffer: proc(target, access: i32) -> rawptr #cc_c;
|
||||
var UnmapBuffer: proc(target: i32) #cc_c;
|
||||
|
||||
VertexAttribPointer: proc(index: u32, size, type_: i32, normalized: i32, stride: u32, pointer: rawptr) #cc_c;
|
||||
EnableVertexAttribArray: proc(index: u32) #cc_c;
|
||||
var VertexAttribPointer: proc(index: u32, size, type_: i32, normalized: i32, stride: u32, pointer: rawptr) #cc_c;
|
||||
var EnableVertexAttribArray: proc(index: u32) #cc_c;
|
||||
|
||||
CreateShader: proc(shader_type: i32) -> u32 #cc_c;
|
||||
ShaderSource: proc(shader: u32, count: u32, str: ^^u8, length: ^i32) #cc_c;
|
||||
CompileShader: proc(shader: u32) #cc_c;
|
||||
CreateProgram: proc() -> u32 #cc_c;
|
||||
AttachShader: proc(program, shader: u32) #cc_c;
|
||||
DetachShader: proc(program, shader: u32) #cc_c;
|
||||
DeleteShader: proc(shader: u32) #cc_c;
|
||||
LinkProgram: proc(program: u32) #cc_c;
|
||||
UseProgram: proc(program: u32) #cc_c;
|
||||
DeleteProgram: proc(program: u32) #cc_c;
|
||||
var CreateShader: proc(shader_type: i32) -> u32 #cc_c;
|
||||
var ShaderSource: proc(shader: u32, count: u32, str: ^^u8, length: ^i32) #cc_c;
|
||||
var CompileShader: proc(shader: u32) #cc_c;
|
||||
var CreateProgram: proc() -> u32 #cc_c;
|
||||
var AttachShader: proc(program, shader: u32) #cc_c;
|
||||
var DetachShader: proc(program, shader: u32) #cc_c;
|
||||
var DeleteShader: proc(shader: u32) #cc_c;
|
||||
var LinkProgram: proc(program: u32) #cc_c;
|
||||
var UseProgram: proc(program: u32) #cc_c;
|
||||
var DeleteProgram: proc(program: u32) #cc_c;
|
||||
|
||||
|
||||
GetShaderiv: proc(shader: u32, pname: i32, params: ^i32) #cc_c;
|
||||
GetProgramiv: proc(program: u32, pname: i32, params: ^i32) #cc_c;
|
||||
GetShaderInfoLog: proc(shader: u32, max_length: u32, length: ^u32, info_long: ^u8) #cc_c;
|
||||
GetProgramInfoLog: proc(program: u32, max_length: u32, length: ^u32, info_long: ^u8) #cc_c;
|
||||
var GetShaderiv: proc(shader: u32, pname: i32, params: ^i32) #cc_c;
|
||||
var GetProgramiv: proc(program: u32, pname: i32, params: ^i32) #cc_c;
|
||||
var GetShaderInfoLog: proc(shader: u32, max_length: u32, length: ^u32, info_long: ^u8) #cc_c;
|
||||
var GetProgramInfoLog: proc(program: u32, max_length: u32, length: ^u32, info_long: ^u8) #cc_c;
|
||||
|
||||
ActiveTexture: proc(texture: i32) #cc_c;
|
||||
GenerateMipmap: proc(target: i32) #cc_c;
|
||||
var ActiveTexture: proc(texture: i32) #cc_c;
|
||||
var GenerateMipmap: proc(target: i32) #cc_c;
|
||||
|
||||
SamplerParameteri: proc(sampler: u32, pname: i32, param: i32) #cc_c;
|
||||
SamplerParameterf: proc(sampler: u32, pname: i32, param: f32) #cc_c;
|
||||
SamplerParameteriv: proc(sampler: u32, pname: i32, params: ^i32) #cc_c;
|
||||
SamplerParameterfv: proc(sampler: u32, pname: i32, params: ^f32) #cc_c;
|
||||
SamplerParameterIiv: proc(sampler: u32, pname: i32, params: ^i32) #cc_c;
|
||||
SamplerParameterIuiv: proc(sampler: u32, pname: i32, params: ^u32) #cc_c;
|
||||
var SamplerParameteri: proc(sampler: u32, pname: i32, param: i32) #cc_c;
|
||||
var SamplerParameterf: proc(sampler: u32, pname: i32, param: f32) #cc_c;
|
||||
var SamplerParameteriv: proc(sampler: u32, pname: i32, params: ^i32) #cc_c;
|
||||
var SamplerParameterfv: proc(sampler: u32, pname: i32, params: ^f32) #cc_c;
|
||||
var SamplerParameterIiv: proc(sampler: u32, pname: i32, params: ^i32) #cc_c;
|
||||
var SamplerParameterIuiv: proc(sampler: u32, pname: i32, params: ^u32) #cc_c;
|
||||
|
||||
|
||||
Uniform1i: proc(loc: i32, v0: i32) #cc_c;
|
||||
Uniform2i: proc(loc: i32, v0, v1: i32) #cc_c;
|
||||
Uniform3i: proc(loc: i32, v0, v1, v2: i32) #cc_c;
|
||||
Uniform4i: proc(loc: i32, v0, v1, v2, v3: i32) #cc_c;
|
||||
Uniform1f: proc(loc: i32, v0: f32) #cc_c;
|
||||
Uniform2f: proc(loc: i32, v0, v1: f32) #cc_c;
|
||||
Uniform3f: proc(loc: i32, v0, v1, v2: f32) #cc_c;
|
||||
Uniform4f: proc(loc: i32, v0, v1, v2, v3: f32) #cc_c;
|
||||
UniformMatrix4fv: proc(loc: i32, count: u32, transpose: i32, value: ^f32) #cc_c;
|
||||
var Uniform1i: proc(loc: i32, v0: i32) #cc_c;
|
||||
var Uniform2i: proc(loc: i32, v0, v1: i32) #cc_c;
|
||||
var Uniform3i: proc(loc: i32, v0, v1, v2: i32) #cc_c;
|
||||
var Uniform4i: proc(loc: i32, v0, v1, v2, v3: i32) #cc_c;
|
||||
var Uniform1f: proc(loc: i32, v0: f32) #cc_c;
|
||||
var Uniform2f: proc(loc: i32, v0, v1: f32) #cc_c;
|
||||
var Uniform3f: proc(loc: i32, v0, v1, v2: f32) #cc_c;
|
||||
var Uniform4f: proc(loc: i32, v0, v1, v2, v3: f32) #cc_c;
|
||||
var UniformMatrix4fv: proc(loc: i32, count: u32, transpose: i32, value: ^f32) #cc_c;
|
||||
|
||||
GetUniformLocation: proc(program: u32, name: ^u8) -> i32 #cc_c;
|
||||
var GetUniformLocation: proc(program: u32, name: ^u8) -> i32 #cc_c;
|
||||
|
||||
init :: proc() {
|
||||
set_proc_address :: proc(p: rawptr, name: string) #inline {
|
||||
x := ^(proc() #cc_c)(p);
|
||||
const init = proc() {
|
||||
const set_proc_address = proc(p: rawptr, name: string) #inline {
|
||||
var x = ^(proc() #cc_c)(p);
|
||||
x^ = get_proc_address(name);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
18
core/os.odin
18
core/os.odin
@@ -2,18 +2,18 @@
|
||||
#load "os_x.odin" when ODIN_OS == "osx";
|
||||
#load "os_linux.odin" when ODIN_OS == "linux";
|
||||
|
||||
write_string :: proc(fd: Handle, str: string) -> (int, Errno) {
|
||||
const write_string = proc(fd: Handle, str: string) -> (int, Errno) {
|
||||
return write(fd, []u8(str));
|
||||
}
|
||||
|
||||
read_entire_file :: proc(name: string) -> ([]u8, bool) {
|
||||
fd, err := open(name, O_RDONLY, 0);
|
||||
const read_entire_file = proc(name: string) -> ([]u8, bool) {
|
||||
var fd, err = open(name, O_RDONLY, 0);
|
||||
if err != 0 {
|
||||
return nil, false;
|
||||
}
|
||||
defer close(fd);
|
||||
|
||||
length: i64;
|
||||
var length: i64;
|
||||
if length, err = file_size(fd); err != 0 {
|
||||
return nil, false;
|
||||
}
|
||||
@@ -22,12 +22,12 @@ read_entire_file :: proc(name: string) -> ([]u8, bool) {
|
||||
return nil, true;
|
||||
}
|
||||
|
||||
data := make([]u8, length);
|
||||
var data = make([]u8, length);
|
||||
if data == nil {
|
||||
return nil, false;
|
||||
}
|
||||
|
||||
bytes_read, read_err := read(fd, data);
|
||||
var bytes_read, read_err = read(fd, data);
|
||||
if read_err != 0 {
|
||||
free(data);
|
||||
return nil, false;
|
||||
@@ -35,13 +35,13 @@ read_entire_file :: proc(name: string) -> ([]u8, bool) {
|
||||
return data[0..<bytes_read], true;
|
||||
}
|
||||
|
||||
write_entire_file :: proc(name: string, data: []u8) -> bool {
|
||||
fd, err := open(name, O_WRONLY, 0);
|
||||
const write_entire_file = proc(name: string, data: []u8) -> bool {
|
||||
var fd, err = open(name, O_WRONLY, 0);
|
||||
if err != 0 {
|
||||
return false;
|
||||
}
|
||||
defer close(fd);
|
||||
|
||||
bytes_written, write_err := write(fd, data);
|
||||
var bytes_written, write_err = write(fd, data);
|
||||
return write_err != 0;
|
||||
}
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
// #import "fmt.odin";
|
||||
#import "strings.odin";
|
||||
|
||||
Handle :: i32;
|
||||
FileTime :: u64;
|
||||
Errno :: i32;
|
||||
const Handle = i32;
|
||||
const FileTime = u64;
|
||||
const Errno = i32;
|
||||
|
||||
// INVALID_HANDLE: Handle : -1;
|
||||
|
||||
O_RDONLY :: 0x00000;
|
||||
O_WRONLY :: 0x00001;
|
||||
O_RDWR :: 0x00002;
|
||||
O_CREAT :: 0x00040;
|
||||
O_EXCL :: 0x00080;
|
||||
O_NOCTTY :: 0x00100;
|
||||
O_TRUNC :: 0x00200;
|
||||
O_NONBLOCK :: 0x00800;
|
||||
O_APPEND :: 0x00400;
|
||||
O_SYNC :: 0x01000;
|
||||
O_ASYNC :: 0x02000;
|
||||
O_CLOEXEC :: 0x80000;
|
||||
SEEK_SET :: 0;
|
||||
SEEK_CUR :: 1;
|
||||
SEEK_END :: 2;
|
||||
SEEK_DATA :: 3;
|
||||
SEEK_HOLE :: 4;
|
||||
SEEK_MAX :: SEEK_HOLE;
|
||||
const O_RDONLY = 0x00000;
|
||||
const O_WRONLY = 0x00001;
|
||||
const O_RDWR = 0x00002;
|
||||
const O_CREAT = 0x00040;
|
||||
const O_EXCL = 0x00080;
|
||||
const O_NOCTTY = 0x00100;
|
||||
const O_TRUNC = 0x00200;
|
||||
const O_NONBLOCK = 0x00800;
|
||||
const O_APPEND = 0x00400;
|
||||
const O_SYNC = 0x01000;
|
||||
const O_ASYNC = 0x02000;
|
||||
const O_CLOEXEC = 0x80000;
|
||||
const SEEK_SET = 0;
|
||||
const SEEK_CUR = 1;
|
||||
const SEEK_END = 2;
|
||||
const SEEK_DATA = 3;
|
||||
const SEEK_HOLE = 4;
|
||||
const SEEK_MAX = SEEK_HOLE;
|
||||
|
||||
// NOTE(zangent): These are OS specific!
|
||||
// Do not mix these up!
|
||||
RTLD_LAZY :: 0x001;
|
||||
RTLD_NOW :: 0x002;
|
||||
RTLD_BINDING_MASK :: 0x3;
|
||||
RTLD_GLOBAL :: 0x100;
|
||||
const RTLD_LAZY = 0x001;
|
||||
const RTLD_NOW = 0x002;
|
||||
const RTLD_BINDING_MASK = 0x3;
|
||||
const RTLD_GLOBAL = 0x100;
|
||||
|
||||
// "Argv" arguments converted to Odin strings
|
||||
immutable args := _alloc_command_line_arguments();
|
||||
immutable var args = _alloc_command_line_arguments();
|
||||
|
||||
_FileTime :: struct #ordered {
|
||||
const _FileTime = struct #ordered {
|
||||
seconds: i64,
|
||||
nanoseconds: i32,
|
||||
reserved: i32,
|
||||
@@ -46,7 +46,7 @@ _FileTime :: struct #ordered {
|
||||
// https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6/+/jb-dev/sysroot/usr/include/bits/stat.h
|
||||
// Validity is not guaranteed.
|
||||
|
||||
Stat :: struct #ordered {
|
||||
const Stat = struct #ordered {
|
||||
device_id: u64, // ID of device containing file
|
||||
serial: u64, // File serial number
|
||||
nlink: u32, // Number of hard links
|
||||
@@ -72,83 +72,83 @@ Stat :: struct #ordered {
|
||||
|
||||
// File type
|
||||
|
||||
S_IFMT :: 0170000; // Type of file mask
|
||||
S_IFIFO :: 0010000; // Named pipe (fifo)
|
||||
S_IFCHR :: 0020000; // Character special
|
||||
S_IFDIR :: 0040000; // Directory
|
||||
S_IFBLK :: 0060000; // Block special
|
||||
S_IFREG :: 0100000; // Regular
|
||||
S_IFLNK :: 0120000; // Symbolic link
|
||||
S_IFSOCK :: 0140000; // Socket
|
||||
const S_IFMT = 0170000; // Type of file mask
|
||||
const S_IFIFO = 0010000; // Named pipe (fifo)
|
||||
const S_IFCHR = 0020000; // Character special
|
||||
const S_IFDIR = 0040000; // Directory
|
||||
const S_IFBLK = 0060000; // Block special
|
||||
const S_IFREG = 0100000; // Regular
|
||||
const S_IFLNK = 0120000; // Symbolic link
|
||||
const S_IFSOCK = 0140000; // Socket
|
||||
|
||||
// File mode
|
||||
// Read, write, execute/search by owner
|
||||
|
||||
S_IRWXU :: 0000700; // RWX mask for owner
|
||||
S_IRUSR :: 0000400; // R for owner
|
||||
S_IWUSR :: 0000200; // W for owner
|
||||
S_IXUSR :: 0000100; // X for owner
|
||||
const S_IRWXU = 0000700; // RWX mask for owner
|
||||
const S_IRUSR = 0000400; // R for owner
|
||||
const S_IWUSR = 0000200; // W for owner
|
||||
const S_IXUSR = 0000100; // X for owner
|
||||
|
||||
// Read, write, execute/search by group
|
||||
|
||||
S_IRWXG :: 0000070; // RWX mask for group
|
||||
S_IRGRP :: 0000040; // R for group
|
||||
S_IWGRP :: 0000020; // W for group
|
||||
S_IXGRP :: 0000010; // X for group
|
||||
const S_IRWXG = 0000070; // RWX mask for group
|
||||
const S_IRGRP = 0000040; // R for group
|
||||
const S_IWGRP = 0000020; // W for group
|
||||
const S_IXGRP = 0000010; // X for group
|
||||
|
||||
// Read, write, execute/search by others
|
||||
|
||||
S_IRWXO :: 0000007; // RWX mask for other
|
||||
S_IROTH :: 0000004; // R for other
|
||||
S_IWOTH :: 0000002; // W for other
|
||||
S_IXOTH :: 0000001; // X for other
|
||||
const S_IRWXO = 0000007; // RWX mask for other
|
||||
const S_IROTH = 0000004; // R for other
|
||||
const S_IWOTH = 0000002; // W for other
|
||||
const S_IXOTH = 0000001; // X for other
|
||||
|
||||
S_ISUID :: 0004000; // Set user id on execution
|
||||
S_ISGID :: 0002000; // Set group id on execution
|
||||
S_ISVTX :: 0001000; // Directory restrcted delete
|
||||
const S_ISUID = 0004000; // Set user id on execution
|
||||
const S_ISGID = 0002000; // Set group id on execution
|
||||
const S_ISVTX = 0001000; // Directory restrcted delete
|
||||
|
||||
S_ISLNK :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFLNK; }
|
||||
S_ISREG :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFREG; }
|
||||
S_ISDIR :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFDIR; }
|
||||
S_ISCHR :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFCHR; }
|
||||
S_ISBLK :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFBLK; }
|
||||
S_ISFIFO :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFIFO; }
|
||||
S_ISSOCK :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFSOCK;}
|
||||
const S_ISLNK = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFLNK; }
|
||||
const S_ISREG = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFREG; }
|
||||
const S_ISDIR = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFDIR; }
|
||||
const S_ISCHR = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFCHR; }
|
||||
const S_ISBLK = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFBLK; }
|
||||
const S_ISFIFO = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFIFO; }
|
||||
const S_ISSOCK = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFSOCK;}
|
||||
|
||||
R_OK :: 4; // Test for read permission
|
||||
W_OK :: 2; // Test for write permission
|
||||
X_OK :: 1; // Test for execute permission
|
||||
F_OK :: 0; // Test for file existance
|
||||
const R_OK = 4; // Test for read permission
|
||||
const W_OK = 2; // Test for write permission
|
||||
const X_OK = 1; // Test for execute permission
|
||||
const F_OK = 0; // Test for file existance
|
||||
|
||||
#foreign_system_library dl "dl";
|
||||
#foreign_system_library libc "c";
|
||||
|
||||
_unix_open :: proc(path: ^u8, mode: int) -> Handle #foreign libc "open";
|
||||
_unix_close :: proc(fd: Handle) -> i32 #foreign libc "close";
|
||||
_unix_read :: proc(fd: Handle, buf: rawptr, size: int) -> int #foreign libc "read";
|
||||
_unix_write :: proc(fd: Handle, buf: rawptr, size: int) -> int #foreign libc "write";
|
||||
_unix_seek :: proc(fd: Handle, offset: i64, whence: i32) -> i64 #foreign libc "lseek64";
|
||||
_unix_gettid :: proc() -> u64 #foreign libc "gettid";
|
||||
_unix_stat :: proc(path: ^u8, stat: ^Stat) -> i32 #foreign libc "stat";
|
||||
_unix_access :: proc(path: ^u8, mask: int) -> i32 #foreign libc "access";
|
||||
const _unix_open = proc(path: ^u8, mode: int) -> Handle #foreign libc "open";
|
||||
const _unix_close = proc(fd: Handle) -> i32 #foreign libc "close";
|
||||
const _unix_read = proc(fd: Handle, buf: rawptr, size: int) -> int #foreign libc "read";
|
||||
const _unix_write = proc(fd: Handle, buf: rawptr, size: int) -> int #foreign libc "write";
|
||||
const _unix_seek = proc(fd: Handle, offset: i64, whence: i32) -> i64 #foreign libc "lseek64";
|
||||
const _unix_gettid = proc() -> u64 #foreign libc "gettid";
|
||||
const _unix_stat = proc(path: ^u8, stat: ^Stat) -> i32 #foreign libc "stat";
|
||||
const _unix_access = proc(path: ^u8, mask: int) -> i32 #foreign libc "access";
|
||||
|
||||
_unix_malloc :: proc(size: int) -> rawptr #foreign libc "malloc";
|
||||
_unix_free :: proc(ptr: rawptr) #foreign libc "free";
|
||||
_unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr #foreign libc "realloc";
|
||||
_unix_getenv :: proc(^u8) -> ^u8 #foreign libc "getenv";
|
||||
const _unix_malloc = proc(size: int) -> rawptr #foreign libc "malloc";
|
||||
const _unix_free = proc(ptr: rawptr) #foreign libc "free";
|
||||
const _unix_realloc = proc(ptr: rawptr, size: int) -> rawptr #foreign libc "realloc";
|
||||
const _unix_getenv = proc(^u8) -> ^u8 #foreign libc "getenv";
|
||||
|
||||
_unix_exit :: proc(status: int) #foreign libc "exit";
|
||||
const _unix_exit = proc(status: int) #foreign libc "exit";
|
||||
|
||||
_unix_dlopen :: proc(filename: ^u8, flags: int) -> rawptr #foreign dl "dlopen";
|
||||
_unix_dlsym :: proc(handle: rawptr, symbol: ^u8) -> (proc() #cc_c) #foreign dl "dlsym";
|
||||
_unix_dlclose :: proc(handle: rawptr) -> int #foreign dl "dlclose";
|
||||
_unix_dlerror :: proc() -> ^u8 #foreign dl "dlerror";
|
||||
const _unix_dlopen = proc(filename: ^u8, flags: int) -> rawptr #foreign dl "dlopen";
|
||||
const _unix_dlsym = proc(handle: rawptr, symbol: ^u8) -> (proc() #cc_c) #foreign dl "dlsym";
|
||||
const _unix_dlclose = proc(handle: rawptr) -> int #foreign dl "dlclose";
|
||||
const _unix_dlerror = proc() -> ^u8 #foreign dl "dlerror";
|
||||
|
||||
// TODO(zangent): Change this to just `open` when Bill fixes overloading.
|
||||
open_simple :: proc(path: string, mode: int) -> (Handle, Errno) {
|
||||
const open_simple = proc(path: string, mode: int) -> (Handle, Errno) {
|
||||
|
||||
cstr := strings.new_c_string(path);
|
||||
handle := _unix_open(cstr, mode);
|
||||
var cstr = strings.new_c_string(path);
|
||||
var handle = _unix_open(cstr, mode);
|
||||
free(cstr);
|
||||
if(handle == -1) {
|
||||
return 0, 1;
|
||||
@@ -156,118 +156,77 @@ open_simple :: proc(path: string, mode: int) -> (Handle, Errno) {
|
||||
return handle, 0;
|
||||
}
|
||||
// NOTE(zangent): This is here for compatability reasons. Should this be here?
|
||||
open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
|
||||
const open = proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
|
||||
return open_simple(path, mode);
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) {
|
||||
const close = proc(fd: Handle) {
|
||||
_unix_close(fd);
|
||||
}
|
||||
|
||||
read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
sz := _unix_read(fd, &data[0], len(data));
|
||||
const read = proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
var sz = _unix_read(fd, &data[0], len(data));
|
||||
return sz, 0;
|
||||
}
|
||||
|
||||
write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
sz := _unix_write(fd, &data[0], len(data));
|
||||
const write = proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
var sz = _unix_write(fd, &data[0], len(data));
|
||||
return sz, 0;
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||
res := _unix_seek(fd, offset, i32(whence));
|
||||
const seek = proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||
var res = _unix_seek(fd, offset, i32(whence));
|
||||
return res, 0;
|
||||
}
|
||||
|
||||
file_size :: proc(fd: Handle) -> (i64, Errno) {
|
||||
prev, _ := seek(fd, 0, SEEK_CUR);
|
||||
size, err := seek(fd, 0, SEEK_END);
|
||||
const file_size = proc(fd: Handle) -> (i64, Errno) {
|
||||
var prev, _ = seek(fd, 0, SEEK_CUR);
|
||||
var size, err = seek(fd, 0, SEEK_END);
|
||||
seek(fd, prev, SEEK_SET);
|
||||
return size, err;
|
||||
}
|
||||
|
||||
|
||||
// NOTE(bill): Uses startup to initialize it
|
||||
stdin: Handle = 0;
|
||||
stdout: Handle = 1;
|
||||
stderr: Handle = 2;
|
||||
var stdin: Handle = 0;
|
||||
var stdout: Handle = 1;
|
||||
var stderr: Handle = 2;
|
||||
|
||||
/* TODO(zangent): Implement these!
|
||||
last_write_time :: proc(fd: Handle) -> FileTime {}
|
||||
last_write_time_by_name :: proc(name: string) -> FileTime {}
|
||||
const last_write_time = proc(fd: Handle) -> FileTime {}
|
||||
const last_write_time_by_name = proc(name: string) -> FileTime {}
|
||||
*/
|
||||
|
||||
stat :: proc(path: string) -> (Stat, int) #inline {
|
||||
s: Stat;
|
||||
cstr := strings.new_c_string(path);
|
||||
const stat = proc(path: string) -> (Stat, int) #inline {
|
||||
var s: Stat;
|
||||
var cstr = strings.new_c_string(path);
|
||||
defer free(cstr);
|
||||
ret_int := _unix_stat(cstr, &s);
|
||||
var ret_int = _unix_stat(cstr, &s);
|
||||
return s, int(ret_int);
|
||||
}
|
||||
|
||||
access :: proc(path: string, mask: int) -> bool #inline {
|
||||
cstr := strings.new_c_string(path);
|
||||
const access = proc(path: string, mask: int) -> bool #inline {
|
||||
var cstr = strings.new_c_string(path);
|
||||
defer free(cstr);
|
||||
return _unix_access(cstr, mask) == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// read_entire_file :: proc(name: string) -> ([]u8, bool) {
|
||||
// fd: Handle;
|
||||
// err: Errno;
|
||||
// size: i64;
|
||||
|
||||
// fd, err = open_simple(name, O_RDONLY);
|
||||
// if(err != 0) {
|
||||
// fmt.println("Failed to open file.");
|
||||
// return nil, false;
|
||||
// }
|
||||
// defer close(fd);
|
||||
|
||||
// // We have a file
|
||||
// size, err = seek(fd, 0, SEEK_END);
|
||||
// if(err != 0) {
|
||||
// fmt.println("Failed to seek to end of file.");
|
||||
// return nil, false;
|
||||
// }
|
||||
|
||||
// _, err = seek(fd, 0, SEEK_SET);
|
||||
// if(err != 0) {
|
||||
// fmt.println("Failed to seek to beginning of file.");
|
||||
// return nil, false;
|
||||
// }
|
||||
|
||||
// // We have a file size!
|
||||
|
||||
// data := make([]u8, size+1);
|
||||
// if data == nil {
|
||||
// fmt.println("Failed to allocate file buffer.");
|
||||
// return nil, false;
|
||||
// }
|
||||
|
||||
// read(fd, data);
|
||||
// data[size] = 0;
|
||||
|
||||
// return data, true;
|
||||
// }
|
||||
|
||||
heap_alloc :: proc(size: int) -> rawptr {
|
||||
const heap_alloc = proc(size: int) -> rawptr {
|
||||
assert(size > 0);
|
||||
return _unix_malloc(size);
|
||||
}
|
||||
|
||||
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
|
||||
const heap_resize = proc(ptr: rawptr, new_size: int) -> rawptr {
|
||||
return _unix_realloc(ptr, new_size);
|
||||
}
|
||||
|
||||
heap_free :: proc(ptr: rawptr) {
|
||||
const heap_free = proc(ptr: rawptr) {
|
||||
_unix_free(ptr);
|
||||
}
|
||||
|
||||
getenv :: proc(name: string) -> (string, bool) {
|
||||
path_str := strings.new_c_string(name);
|
||||
cstr: ^u8 = _unix_getenv(path_str);
|
||||
const getenv = proc(name: string) -> (string, bool) {
|
||||
var path_str = strings.new_c_string(name);
|
||||
var cstr: ^u8 = _unix_getenv(path_str);
|
||||
free(path_str);
|
||||
if(cstr == nil) {
|
||||
return "", false;
|
||||
@@ -275,38 +234,38 @@ getenv :: proc(name: string) -> (string, bool) {
|
||||
return strings.to_odin_string(cstr), true;
|
||||
}
|
||||
|
||||
exit :: proc(code: int) {
|
||||
const exit = proc(code: int) {
|
||||
_unix_exit(code);
|
||||
}
|
||||
|
||||
current_thread_id :: proc() -> int {
|
||||
const current_thread_id = proc() -> int {
|
||||
// return int(_unix_gettid());
|
||||
return 0;
|
||||
}
|
||||
|
||||
dlopen :: proc(filename: string, flags: int) -> rawptr #inline {
|
||||
cstr := strings.new_c_string(filename);
|
||||
handle := _unix_dlopen(cstr, flags);
|
||||
const dlopen = proc(filename: string, flags: int) -> rawptr #inline {
|
||||
var cstr = strings.new_c_string(filename);
|
||||
var handle = _unix_dlopen(cstr, flags);
|
||||
free(cstr);
|
||||
return handle;
|
||||
}
|
||||
dlsym :: proc(handle: rawptr, symbol: string) -> (proc() #cc_c) #inline {
|
||||
const dlsym = proc(handle: rawptr, symbol: string) -> (proc() #cc_c) #inline {
|
||||
assert(handle != nil);
|
||||
cstr := strings.new_c_string(symbol);
|
||||
proc_handle := _unix_dlsym(handle, cstr);
|
||||
var cstr = strings.new_c_string(symbol);
|
||||
var proc_handle = _unix_dlsym(handle, cstr);
|
||||
free(cstr);
|
||||
return proc_handle;
|
||||
}
|
||||
dlclose :: proc(handle: rawptr) -> bool #inline {
|
||||
const dlclose = proc(handle: rawptr) -> bool #inline {
|
||||
assert(handle != nil);
|
||||
return _unix_dlclose(handle) == 0;
|
||||
}
|
||||
dlerror :: proc() -> string {
|
||||
const dlerror = proc() -> string {
|
||||
return strings.to_odin_string(_unix_dlerror());
|
||||
}
|
||||
|
||||
|
||||
_alloc_command_line_arguments :: proc() -> []string {
|
||||
const _alloc_command_line_arguments = proc() -> []string {
|
||||
// TODO(bill):
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -1,63 +1,63 @@
|
||||
#import win32 "sys/windows.odin";
|
||||
|
||||
Handle :: int;
|
||||
FileTime :: u64;
|
||||
Errno :: int;
|
||||
const Handle = int;
|
||||
const FileTime = u64;
|
||||
const Errno = int;
|
||||
|
||||
INVALID_HANDLE: Handle : -1;
|
||||
const INVALID_HANDLE: Handle = -1;
|
||||
|
||||
|
||||
O_RDONLY :: 0x00000;
|
||||
O_WRONLY :: 0x00001;
|
||||
O_RDWR :: 0x00002;
|
||||
O_CREAT :: 0x00040;
|
||||
O_EXCL :: 0x00080;
|
||||
O_NOCTTY :: 0x00100;
|
||||
O_TRUNC :: 0x00200;
|
||||
O_NONBLOCK :: 0x00800;
|
||||
O_APPEND :: 0x00400;
|
||||
O_SYNC :: 0x01000;
|
||||
O_ASYNC :: 0x02000;
|
||||
O_CLOEXEC :: 0x80000;
|
||||
const O_RDONLY = 0x00000;
|
||||
const O_WRONLY = 0x00001;
|
||||
const O_RDWR = 0x00002;
|
||||
const O_CREAT = 0x00040;
|
||||
const O_EXCL = 0x00080;
|
||||
const O_NOCTTY = 0x00100;
|
||||
const O_TRUNC = 0x00200;
|
||||
const O_NONBLOCK = 0x00800;
|
||||
const O_APPEND = 0x00400;
|
||||
const O_SYNC = 0x01000;
|
||||
const O_ASYNC = 0x02000;
|
||||
const O_CLOEXEC = 0x80000;
|
||||
|
||||
ERROR_NONE: Errno : 0;
|
||||
ERROR_FILE_NOT_FOUND: Errno : 2;
|
||||
ERROR_PATH_NOT_FOUND: Errno : 3;
|
||||
ERROR_ACCESS_DENIED: Errno : 5;
|
||||
ERROR_NO_MORE_FILES: Errno : 18;
|
||||
ERROR_HANDLE_EOF: Errno : 38;
|
||||
ERROR_NETNAME_DELETED: Errno : 64;
|
||||
ERROR_FILE_EXISTS: Errno : 80;
|
||||
ERROR_BROKEN_PIPE: Errno : 109;
|
||||
ERROR_BUFFER_OVERFLOW: Errno : 111;
|
||||
ERROR_INSUFFICIENT_BUFFER: Errno : 122;
|
||||
ERROR_MOD_NOT_FOUND: Errno : 126;
|
||||
ERROR_PROC_NOT_FOUND: Errno : 127;
|
||||
ERROR_DIR_NOT_EMPTY: Errno : 145;
|
||||
ERROR_ALREADY_EXISTS: Errno : 183;
|
||||
ERROR_ENVVAR_NOT_FOUND: Errno : 203;
|
||||
ERROR_MORE_DATA: Errno : 234;
|
||||
ERROR_OPERATION_ABORTED: Errno : 995;
|
||||
ERROR_IO_PENDING: Errno : 997;
|
||||
ERROR_NOT_FOUND: Errno : 1168;
|
||||
ERROR_PRIVILEGE_NOT_HELD: Errno : 1314;
|
||||
WSAEACCES: Errno : 10013;
|
||||
WSAECONNRESET: Errno : 10054;
|
||||
const ERROR_NONE: Errno = 0;
|
||||
const ERROR_FILE_NOT_FOUND: Errno = 2;
|
||||
const ERROR_PATH_NOT_FOUND: Errno = 3;
|
||||
const ERROR_ACCESS_DENIED: Errno = 5;
|
||||
const ERROR_NO_MORE_FILES: Errno = 18;
|
||||
const ERROR_HANDLE_EOF: Errno = 38;
|
||||
const ERROR_NETNAME_DELETED: Errno = 64;
|
||||
const ERROR_FILE_EXISTS: Errno = 80;
|
||||
const ERROR_BROKEN_PIPE: Errno = 109;
|
||||
const ERROR_BUFFER_OVERFLOW: Errno = 111;
|
||||
const ERROR_INSUFFICIENT_BUFFER: Errno = 122;
|
||||
const ERROR_MOD_NOT_FOUND: Errno = 126;
|
||||
const ERROR_PROC_NOT_FOUND: Errno = 127;
|
||||
const ERROR_DIR_NOT_EMPTY: Errno = 145;
|
||||
const ERROR_ALREADY_EXISTS: Errno = 183;
|
||||
const ERROR_ENVVAR_NOT_FOUND: Errno = 203;
|
||||
const ERROR_MORE_DATA: Errno = 234;
|
||||
const ERROR_OPERATION_ABORTED: Errno = 995;
|
||||
const ERROR_IO_PENDING: Errno = 997;
|
||||
const ERROR_NOT_FOUND: Errno = 1168;
|
||||
const ERROR_PRIVILEGE_NOT_HELD: Errno = 1314;
|
||||
const WSAEACCES: Errno = 10013;
|
||||
const WSAECONNRESET: Errno = 10054;
|
||||
|
||||
// Windows reserves errors >= 1<<29 for application use
|
||||
ERROR_FILE_IS_PIPE: Errno : 1<<29 + 0;
|
||||
const ERROR_FILE_IS_PIPE: Errno = 1<<29 + 0;
|
||||
|
||||
|
||||
// "Argv" arguments converted to Odin strings
|
||||
immutable args := _alloc_command_line_arguments();
|
||||
immutable var args = _alloc_command_line_arguments();
|
||||
|
||||
|
||||
open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
|
||||
const open = proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
|
||||
if len(path) == 0 {
|
||||
return INVALID_HANDLE, ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
access: u32;
|
||||
var access: u32;
|
||||
match mode & (O_RDONLY|O_WRONLY|O_RDWR) {
|
||||
case O_RDONLY: access = win32.FILE_GENERIC_READ;
|
||||
case O_WRONLY: access = win32.FILE_GENERIC_WRITE;
|
||||
@@ -72,14 +72,14 @@ open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
|
||||
access |= win32.FILE_APPEND_DATA;
|
||||
}
|
||||
|
||||
share_mode := u32(win32.FILE_SHARE_READ|win32.FILE_SHARE_WRITE);
|
||||
sa: ^win32.Security_Attributes = nil;
|
||||
sa_inherit := win32.Security_Attributes{length = size_of(win32.Security_Attributes), inherit_handle = 1};
|
||||
var share_mode = u32(win32.FILE_SHARE_READ|win32.FILE_SHARE_WRITE);
|
||||
var sa: ^win32.Security_Attributes = nil;
|
||||
var sa_inherit = win32.Security_Attributes{length = size_of(win32.Security_Attributes), inherit_handle = 1};
|
||||
if mode&O_CLOEXEC == 0 {
|
||||
sa = &sa_inherit;
|
||||
}
|
||||
|
||||
create_mode: u32;
|
||||
var create_mode: u32;
|
||||
match {
|
||||
case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
|
||||
create_mode = win32.CREATE_NEW;
|
||||
@@ -93,42 +93,42 @@ open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
|
||||
create_mode = win32.OPEN_EXISTING;
|
||||
}
|
||||
|
||||
buf: [300]u8;
|
||||
var buf: [300]u8;
|
||||
copy(buf[..], []u8(path));
|
||||
|
||||
handle := Handle(win32.create_file_a(&buf[0], access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil));
|
||||
var handle = Handle(win32.create_file_a(&buf[0], access, share_mode, sa, create_mode, win32.FILE_ATTRIBUTE_NORMAL, nil));
|
||||
if handle != INVALID_HANDLE {
|
||||
return handle, ERROR_NONE;
|
||||
}
|
||||
err := win32.get_last_error();
|
||||
var err = win32.get_last_error();
|
||||
return INVALID_HANDLE, Errno(err);
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) {
|
||||
const close = proc(fd: Handle) {
|
||||
win32.close_handle(win32.Handle(fd));
|
||||
}
|
||||
|
||||
|
||||
write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
const write = proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
if len(data) == 0 {
|
||||
return 0, ERROR_NONE;
|
||||
}
|
||||
single_write_length: i32;
|
||||
total_write: i64;
|
||||
length := i64(len(data));
|
||||
var single_write_length: i32;
|
||||
var total_write: i64;
|
||||
var length = i64(len(data));
|
||||
|
||||
for total_write < length {
|
||||
remaining := length - total_write;
|
||||
to_read: i32;
|
||||
MAX :: 1<<31-1;
|
||||
var remaining = length - total_write;
|
||||
var to_read: i32;
|
||||
const MAX = 1<<31-1;
|
||||
if remaining <= MAX {
|
||||
to_read = i32(remaining);
|
||||
} else {
|
||||
to_read = MAX;
|
||||
}
|
||||
e := win32.write_file(win32.Handle(fd), &data[total_write], to_read, &single_write_length, nil);
|
||||
var e = win32.write_file(win32.Handle(fd), &data[total_write], to_read, &single_write_length, nil);
|
||||
if single_write_length <= 0 || e == win32.FALSE {
|
||||
err := win32.get_last_error();
|
||||
var err = win32.get_last_error();
|
||||
return int(total_write), Errno(e);
|
||||
}
|
||||
total_write += i64(single_write_length);
|
||||
@@ -136,28 +136,28 @@ write :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
return int(total_write), ERROR_NONE;
|
||||
}
|
||||
|
||||
read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
const read = proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
if len(data) == 0 {
|
||||
return 0, ERROR_NONE;
|
||||
}
|
||||
|
||||
single_read_length: i32;
|
||||
total_read: i64;
|
||||
length := i64(len(data));
|
||||
var single_read_length: i32;
|
||||
var total_read: i64;
|
||||
var length = i64(len(data));
|
||||
|
||||
for total_read < length {
|
||||
remaining := length - total_read;
|
||||
to_read: u32;
|
||||
MAX :: 1<<32-1;
|
||||
var remaining = length - total_read;
|
||||
var to_read: u32;
|
||||
const MAX = 1<<32-1;
|
||||
if remaining <= MAX {
|
||||
to_read = u32(remaining);
|
||||
} else {
|
||||
to_read = MAX;
|
||||
}
|
||||
|
||||
e := win32.read_file(win32.Handle(fd), &data[total_read], to_read, &single_read_length, nil);
|
||||
var e = win32.read_file(win32.Handle(fd), &data[total_read], to_read, &single_read_length, nil);
|
||||
if single_read_length <= 0 || e == win32.FALSE {
|
||||
err := win32.get_last_error();
|
||||
var err = win32.get_last_error();
|
||||
return int(total_read), Errno(e);
|
||||
}
|
||||
total_read += i64(single_read_length);
|
||||
@@ -165,30 +165,30 @@ read :: proc(fd: Handle, data: []u8) -> (int, Errno) {
|
||||
return int(total_read), ERROR_NONE;
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||
w: u32;
|
||||
const seek = proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||
var w: u32;
|
||||
match whence {
|
||||
case 0: w = win32.FILE_BEGIN;
|
||||
case 1: w = win32.FILE_CURRENT;
|
||||
case 2: w = win32.FILE_END;
|
||||
}
|
||||
hi := i32(offset>>32);
|
||||
lo := i32(offset);
|
||||
ft := win32.get_file_type(win32.Handle(fd));
|
||||
var hi = i32(offset>>32);
|
||||
var lo = i32(offset);
|
||||
var ft = win32.get_file_type(win32.Handle(fd));
|
||||
if ft == win32.FILE_TYPE_PIPE {
|
||||
return 0, ERROR_FILE_IS_PIPE;
|
||||
}
|
||||
dw_ptr := win32.set_file_pointer(win32.Handle(fd), lo, &hi, w);
|
||||
var dw_ptr = win32.set_file_pointer(win32.Handle(fd), lo, &hi, w);
|
||||
if dw_ptr == win32.INVALID_SET_FILE_POINTER {
|
||||
err := win32.get_last_error();
|
||||
var err = win32.get_last_error();
|
||||
return 0, Errno(err);
|
||||
}
|
||||
return i64(hi)<<32 + i64(dw_ptr), ERROR_NONE;
|
||||
}
|
||||
|
||||
file_size :: proc(fd: Handle) -> (i64, Errno) {
|
||||
length: i64;
|
||||
err: Errno;
|
||||
const file_size = proc(fd: Handle) -> (i64, Errno) {
|
||||
var length: i64;
|
||||
var err: Errno;
|
||||
if win32.get_file_size_ex(win32.Handle(fd), &length) == 0 {
|
||||
err = Errno(win32.get_last_error());
|
||||
}
|
||||
@@ -198,13 +198,13 @@ file_size :: proc(fd: Handle) -> (i64, Errno) {
|
||||
|
||||
|
||||
// NOTE(bill): Uses startup to initialize it
|
||||
stdin := get_std_handle(win32.STD_INPUT_HANDLE);
|
||||
stdout := get_std_handle(win32.STD_OUTPUT_HANDLE);
|
||||
stderr := get_std_handle(win32.STD_ERROR_HANDLE);
|
||||
var stdin = get_std_handle(win32.STD_INPUT_HANDLE);
|
||||
var stdout = get_std_handle(win32.STD_OUTPUT_HANDLE);
|
||||
var stderr = get_std_handle(win32.STD_ERROR_HANDLE);
|
||||
|
||||
|
||||
get_std_handle :: proc(h: int) -> Handle {
|
||||
fd := win32.get_std_handle(i32(h));
|
||||
const get_std_handle = proc(h: int) -> Handle {
|
||||
var fd = win32.get_std_handle(i32(h));
|
||||
win32.set_handle_information(fd, win32.HANDLE_FLAG_INHERIT, 0);
|
||||
return Handle(fd);
|
||||
}
|
||||
@@ -214,18 +214,18 @@ get_std_handle :: proc(h: int) -> Handle {
|
||||
|
||||
|
||||
|
||||
last_write_time :: proc(fd: Handle) -> FileTime {
|
||||
file_info: win32.ByHandleFileInformation;
|
||||
const last_write_time = proc(fd: Handle) -> FileTime {
|
||||
var file_info: win32.ByHandleFileInformation;
|
||||
win32.get_file_information_by_handle(win32.Handle(fd), &file_info);
|
||||
lo := FileTime(file_info.last_write_time.lo);
|
||||
hi := FileTime(file_info.last_write_time.hi);
|
||||
var lo = FileTime(file_info.last_write_time.lo);
|
||||
var hi = FileTime(file_info.last_write_time.hi);
|
||||
return lo | hi << 32;
|
||||
}
|
||||
|
||||
last_write_time_by_name :: proc(name: string) -> FileTime {
|
||||
last_write_time: win32.Filetime;
|
||||
data: win32.FileAttributeData;
|
||||
buf: [1024]u8;
|
||||
const last_write_time_by_name = proc(name: string) -> FileTime {
|
||||
var last_write_time: win32.Filetime;
|
||||
var data: win32.FileAttributeData;
|
||||
var buf: [1024]u8;
|
||||
|
||||
assert(len(buf) > len(name));
|
||||
|
||||
@@ -235,17 +235,17 @@ last_write_time_by_name :: proc(name: string) -> FileTime {
|
||||
last_write_time = data.last_write_time;
|
||||
}
|
||||
|
||||
l := FileTime(last_write_time.lo);
|
||||
h := FileTime(last_write_time.hi);
|
||||
var l = FileTime(last_write_time.lo);
|
||||
var h = FileTime(last_write_time.hi);
|
||||
return l | h << 32;
|
||||
}
|
||||
|
||||
|
||||
|
||||
heap_alloc :: proc(size: int) -> rawptr {
|
||||
const heap_alloc = proc(size: int) -> rawptr {
|
||||
return win32.heap_alloc(win32.get_process_heap(), win32.HEAP_ZERO_MEMORY, size);
|
||||
}
|
||||
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
|
||||
const heap_resize = proc(ptr: rawptr, new_size: int) -> rawptr {
|
||||
if new_size == 0 {
|
||||
heap_free(ptr);
|
||||
return nil;
|
||||
@@ -255,7 +255,7 @@ heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
|
||||
}
|
||||
return win32.heap_realloc(win32.get_process_heap(), win32.HEAP_ZERO_MEMORY, ptr, new_size);
|
||||
}
|
||||
heap_free :: proc(ptr: rawptr) {
|
||||
const heap_free = proc(ptr: rawptr) {
|
||||
if ptr == nil {
|
||||
return;
|
||||
}
|
||||
@@ -263,30 +263,30 @@ heap_free :: proc(ptr: rawptr) {
|
||||
}
|
||||
|
||||
|
||||
exit :: proc(code: int) {
|
||||
const exit = proc(code: int) {
|
||||
win32.exit_process(u32(code));
|
||||
}
|
||||
|
||||
|
||||
|
||||
current_thread_id :: proc() -> int {
|
||||
const current_thread_id = proc() -> int {
|
||||
return int(win32.get_current_thread_id());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
_alloc_command_line_arguments :: proc() -> []string {
|
||||
alloc_ucs2_to_utf8 :: proc(wstr: ^u16) -> string {
|
||||
wstr_len := 0;
|
||||
const _alloc_command_line_arguments = proc() -> []string {
|
||||
const alloc_ucs2_to_utf8 = proc(wstr: ^u16) -> string {
|
||||
var wstr_len = 0;
|
||||
for (wstr+wstr_len)^ != 0 {
|
||||
wstr_len++;
|
||||
}
|
||||
len := 2*wstr_len-1;
|
||||
buf := make([]u8, len+1);
|
||||
str := slice_ptr(wstr, wstr_len+1);
|
||||
var len = 2*wstr_len-1;
|
||||
var buf = make([]u8, len+1);
|
||||
var str = slice_ptr(wstr, wstr_len+1);
|
||||
|
||||
i, j := 0, 0;
|
||||
var i, j = 0, 0;
|
||||
for str[j] != 0 {
|
||||
match {
|
||||
case str[j] < 0x80:
|
||||
@@ -306,7 +306,7 @@ _alloc_command_line_arguments :: proc() -> []string {
|
||||
if i+4 > len {
|
||||
return "";
|
||||
}
|
||||
c := rune((str[j] - 0xd800) << 10) + rune((str[j+1]) - 0xdc00) + 0x10000;
|
||||
var c = rune((str[j] - 0xd800) << 10) + rune((str[j+1]) - 0xdc00) + 0x10000;
|
||||
buf[i] = u8(0xf0 + (c >> 18)); i++;
|
||||
buf[i] = u8(0x80 + ((c >> 12) & 0x3f)); i++;
|
||||
buf[i] = u8(0x80 + ((c >> 6) & 0x3f)); i++;
|
||||
@@ -328,9 +328,9 @@ _alloc_command_line_arguments :: proc() -> []string {
|
||||
return string(buf[0..<i]);
|
||||
}
|
||||
|
||||
arg_count: i32;
|
||||
arg_list_ptr := win32.command_line_to_argv_w(win32.get_command_line_w(), &arg_count);
|
||||
arg_list := make([]string, arg_count);
|
||||
var arg_count: i32;
|
||||
var arg_list_ptr = win32.command_line_to_argv_w(win32.get_command_line_w(), &arg_count);
|
||||
var arg_list = make([]string, arg_count);
|
||||
for _, i in arg_list {
|
||||
arg_list[i] = alloc_ucs2_to_utf8((arg_list_ptr+i)^);
|
||||
}
|
||||
|
||||
286
core/os_x.odin
286
core/os_x.odin
@@ -1,52 +1,52 @@
|
||||
#import "fmt.odin";
|
||||
#import "strings.odin";
|
||||
|
||||
Handle :: i32;
|
||||
FileTime :: u64;
|
||||
Errno :: int;
|
||||
const Handle = i32;
|
||||
const FileTime = u64;
|
||||
const Errno = int;
|
||||
|
||||
// TODO(zangent): Find out how to make this work on x64 and x32.
|
||||
AddressSize :: i64;
|
||||
const AddressSize = i64;
|
||||
|
||||
// INVALID_HANDLE: Handle : -1;
|
||||
|
||||
O_RDONLY :: 0x00000;
|
||||
O_WRONLY :: 0x00001;
|
||||
O_RDWR :: 0x00002;
|
||||
O_CREAT :: 0x00040;
|
||||
O_EXCL :: 0x00080;
|
||||
O_NOCTTY :: 0x00100;
|
||||
O_TRUNC :: 0x00200;
|
||||
O_NONBLOCK :: 0x00800;
|
||||
O_APPEND :: 0x00400;
|
||||
O_SYNC :: 0x01000;
|
||||
O_ASYNC :: 0x02000;
|
||||
O_CLOEXEC :: 0x80000;
|
||||
SEEK_SET :: 0;
|
||||
SEEK_CUR :: 1;
|
||||
SEEK_END :: 2;
|
||||
SEEK_DATA :: 3;
|
||||
SEEK_HOLE :: 4;
|
||||
SEEK_MAX :: SEEK_HOLE;
|
||||
const O_RDONLY = 0x00000;
|
||||
const O_WRONLY = 0x00001;
|
||||
const O_RDWR = 0x00002;
|
||||
const O_CREAT = 0x00040;
|
||||
const O_EXCL = 0x00080;
|
||||
const O_NOCTTY = 0x00100;
|
||||
const O_TRUNC = 0x00200;
|
||||
const O_NONBLOCK = 0x00800;
|
||||
const O_APPEND = 0x00400;
|
||||
const O_SYNC = 0x01000;
|
||||
const O_ASYNC = 0x02000;
|
||||
const O_CLOEXEC = 0x80000;
|
||||
const SEEK_SET = 0;
|
||||
const SEEK_CUR = 1;
|
||||
const SEEK_END = 2;
|
||||
const SEEK_DATA = 3;
|
||||
const SEEK_HOLE = 4;
|
||||
const SEEK_MAX = SEEK_HOLE;
|
||||
|
||||
// NOTE(zangent): These are OS specific!
|
||||
// Do not mix these up!
|
||||
RTLD_LAZY :: 0x1;
|
||||
RTLD_NOW :: 0x2;
|
||||
RTLD_LOCAL :: 0x4;
|
||||
RTLD_GLOBAL :: 0x8;
|
||||
RTLD_NODELETE :: 0x80;
|
||||
RTLD_NOLOAD :: 0x10;
|
||||
RTLD_FIRST :: 0x100;
|
||||
const RTLD_LAZY = 0x1;
|
||||
const RTLD_NOW = 0x2;
|
||||
const RTLD_LOCAL = 0x4;
|
||||
const RTLD_GLOBAL = 0x8;
|
||||
const RTLD_NODELETE = 0x80;
|
||||
const RTLD_NOLOAD = 0x10;
|
||||
const RTLD_FIRST = 0x100;
|
||||
|
||||
args: [dynamic]string;
|
||||
var args: [dynamic]string;
|
||||
|
||||
_FileTime :: struct #ordered {
|
||||
const _FileTime = struct #ordered {
|
||||
seconds: i64,
|
||||
nanoseconds: i64
|
||||
}
|
||||
|
||||
Stat :: struct #ordered {
|
||||
const Stat = struct #ordered {
|
||||
device_id : i32, // ID of device containing file
|
||||
mode : u16, // Mode of the file
|
||||
nlink : u16, // Number of hard links
|
||||
@@ -72,84 +72,84 @@ Stat :: struct #ordered {
|
||||
|
||||
// File type
|
||||
|
||||
S_IFMT :: 0170000; // Type of file mask
|
||||
S_IFIFO :: 0010000; // Named pipe (fifo)
|
||||
S_IFCHR :: 0020000; // Character special
|
||||
S_IFDIR :: 0040000; // Directory
|
||||
S_IFBLK :: 0060000; // Block special
|
||||
S_IFREG :: 0100000; // Regular
|
||||
S_IFLNK :: 0120000; // Symbolic link
|
||||
S_IFSOCK :: 0140000; // Socket
|
||||
const S_IFMT = 0170000; // Type of file mask
|
||||
const S_IFIFO = 0010000; // Named pipe (fifo)
|
||||
const S_IFCHR = 0020000; // Character special
|
||||
const S_IFDIR = 0040000; // Directory
|
||||
const S_IFBLK = 0060000; // Block special
|
||||
const S_IFREG = 0100000; // Regular
|
||||
const S_IFLNK = 0120000; // Symbolic link
|
||||
const S_IFSOCK = 0140000; // Socket
|
||||
|
||||
// File mode
|
||||
// Read, write, execute/search by owner
|
||||
|
||||
S_IRWXU :: 0000700; // RWX mask for owner
|
||||
S_IRUSR :: 0000400; // R for owner
|
||||
S_IWUSR :: 0000200; // W for owner
|
||||
S_IXUSR :: 0000100; // X for owner
|
||||
const S_IRWXU = 0000700; // RWX mask for owner
|
||||
const S_IRUSR = 0000400; // R for owner
|
||||
const S_IWUSR = 0000200; // W for owner
|
||||
const S_IXUSR = 0000100; // X for owner
|
||||
|
||||
// Read, write, execute/search by group
|
||||
|
||||
S_IRWXG :: 0000070; // RWX mask for group
|
||||
S_IRGRP :: 0000040; // R for group
|
||||
S_IWGRP :: 0000020; // W for group
|
||||
S_IXGRP :: 0000010; // X for group
|
||||
const S_IRWXG = 0000070; // RWX mask for group
|
||||
const S_IRGRP = 0000040; // R for group
|
||||
const S_IWGRP = 0000020; // W for group
|
||||
const S_IXGRP = 0000010; // X for group
|
||||
|
||||
// Read, write, execute/search by others
|
||||
|
||||
S_IRWXO :: 0000007; // RWX mask for other
|
||||
S_IROTH :: 0000004; // R for other
|
||||
S_IWOTH :: 0000002; // W for other
|
||||
S_IXOTH :: 0000001; // X for other
|
||||
const S_IRWXO = 0000007; // RWX mask for other
|
||||
const S_IROTH = 0000004; // R for other
|
||||
const S_IWOTH = 0000002; // W for other
|
||||
const S_IXOTH = 0000001; // X for other
|
||||
|
||||
S_ISUID :: 0004000; // Set user id on execution
|
||||
S_ISGID :: 0002000; // Set group id on execution
|
||||
S_ISVTX :: 0001000; // Directory restrcted delete
|
||||
const S_ISUID = 0004000; // Set user id on execution
|
||||
const S_ISGID = 0002000; // Set group id on execution
|
||||
const S_ISVTX = 0001000; // Directory restrcted delete
|
||||
|
||||
S_ISLNK :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFLNK; }
|
||||
S_ISREG :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFREG; }
|
||||
S_ISDIR :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFDIR; }
|
||||
S_ISCHR :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFCHR; }
|
||||
S_ISBLK :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFBLK; }
|
||||
S_ISFIFO :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFIFO; }
|
||||
S_ISSOCK :: proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFSOCK;}
|
||||
const S_ISLNK = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFLNK; }
|
||||
const S_ISREG = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFREG; }
|
||||
const S_ISDIR = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFDIR; }
|
||||
const S_ISCHR = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFCHR; }
|
||||
const S_ISBLK = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFBLK; }
|
||||
const S_ISFIFO = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFIFO; }
|
||||
const S_ISSOCK = proc(m: u32) -> bool #inline {return ((m) & S_IFMT) == S_IFSOCK;}
|
||||
|
||||
R_OK :: 4; // Test for read permission
|
||||
W_OK :: 2; // Test for write permission
|
||||
X_OK :: 1; // Test for execute permission
|
||||
F_OK :: 0; // Test for file existance
|
||||
const R_OK = 4; // Test for read permission
|
||||
const W_OK = 2; // Test for write permission
|
||||
const X_OK = 1; // Test for execute permission
|
||||
const F_OK = 0; // Test for file existance
|
||||
|
||||
#foreign_system_library dl "dl";
|
||||
#foreign_system_library libc "c";
|
||||
|
||||
unix_open :: proc(path: ^u8, mode: int) -> Handle #foreign libc "open";
|
||||
unix_close :: proc(handle: Handle) #foreign libc "close";
|
||||
unix_read :: proc(handle: Handle, buffer: rawptr, count: int) -> AddressSize #foreign libc "read";
|
||||
unix_write :: proc(handle: Handle, buffer: rawptr, count: int) -> AddressSize #foreign libc "write";
|
||||
unix_lseek :: proc(fs: Handle, offset: AddressSize, whence: int) -> AddressSize #foreign libc "lseek";
|
||||
unix_gettid :: proc() -> u64 #foreign libc "gettid";
|
||||
unix_stat :: proc(path: ^u8, stat: ^Stat) -> int #foreign libc "stat";
|
||||
unix_access :: proc(path: ^u8, mask: int) -> int #foreign libc "access";
|
||||
const unix_open = proc(path: ^u8, mode: int) -> Handle #foreign libc "open";
|
||||
const unix_close = proc(handle: Handle) #foreign libc "close";
|
||||
const unix_read = proc(handle: Handle, buffer: rawptr, count: int) -> AddressSize #foreign libc "read";
|
||||
const unix_write = proc(handle: Handle, buffer: rawptr, count: int) -> AddressSize #foreign libc "write";
|
||||
const unix_lseek = proc(fs: Handle, offset: AddressSize, whence: int) -> AddressSize #foreign libc "lseek";
|
||||
const unix_gettid = proc() -> u64 #foreign libc "gettid";
|
||||
const unix_stat = proc(path: ^u8, stat: ^Stat) -> int #foreign libc "stat";
|
||||
const unix_access = proc(path: ^u8, mask: int) -> int #foreign libc "access";
|
||||
|
||||
unix_malloc :: proc(size: int) -> rawptr #foreign libc "malloc";
|
||||
unix_free :: proc(ptr: rawptr) #foreign libc "free";
|
||||
unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr #foreign libc "realloc";
|
||||
unix_getenv :: proc(^u8) -> ^u8 #foreign libc "getenv";
|
||||
const unix_malloc = proc(size: int) -> rawptr #foreign libc "malloc";
|
||||
const unix_free = proc(ptr: rawptr) #foreign libc "free";
|
||||
const unix_realloc = proc(ptr: rawptr, size: int) -> rawptr #foreign libc "realloc";
|
||||
const unix_getenv = proc(^u8) -> ^u8 #foreign libc "getenv";
|
||||
|
||||
unix_exit :: proc(status: int) #foreign libc "exit";
|
||||
const unix_exit = proc(status: int) #foreign libc "exit";
|
||||
|
||||
unix_dlopen :: proc(filename: ^u8, flags: int) -> rawptr #foreign dl "dlopen";
|
||||
unix_dlsym :: proc(handle: rawptr, symbol: ^u8) -> (proc() #cc_c) #foreign dl "dlsym";
|
||||
unix_dlclose :: proc(handle: rawptr) -> int #foreign dl "dlclose";
|
||||
unix_dlerror :: proc() -> ^u8 #foreign dl "dlerror";
|
||||
const unix_dlopen = proc(filename: ^u8, flags: int) -> rawptr #foreign dl "dlopen";
|
||||
const unix_dlsym = proc(handle: rawptr, symbol: ^u8) -> (proc() #cc_c) #foreign dl "dlsym";
|
||||
const unix_dlclose = proc(handle: rawptr) -> int #foreign dl "dlclose";
|
||||
const unix_dlerror = proc() -> ^u8 #foreign dl "dlerror";
|
||||
|
||||
|
||||
// TODO(zangent): Change this to just `open` when Bill fixes overloading.
|
||||
open_simple :: proc(path: string, mode: int) -> (Handle, Errno) {
|
||||
const open_simple = proc(path: string, mode: int) -> (Handle, Errno) {
|
||||
|
||||
cstr := strings.new_c_string(path);
|
||||
handle := unix_open(cstr, mode);
|
||||
var cstr = strings.new_c_string(path);
|
||||
var handle = unix_open(cstr, mode);
|
||||
free(cstr);
|
||||
if(handle == -1) {
|
||||
return 0, 1;
|
||||
@@ -158,47 +158,47 @@ open_simple :: proc(path: string, mode: int) -> (Handle, Errno) {
|
||||
}
|
||||
|
||||
// NOTE(zangent): This is here for compatability reasons. Should this be here?
|
||||
open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
|
||||
const open = proc(path: string, mode: int, perm: u32) -> (Handle, Errno) {
|
||||
return open_simple(path, mode);
|
||||
}
|
||||
|
||||
close :: proc(fd: Handle) {
|
||||
const close = proc(fd: Handle) {
|
||||
unix_close(fd);
|
||||
}
|
||||
|
||||
write :: proc(fd: Handle, data: []u8) -> (AddressSize, Errno) {
|
||||
const write = proc(fd: Handle, data: []u8) -> (AddressSize, Errno) {
|
||||
assert(fd != -1);
|
||||
|
||||
bytes_written := unix_write(fd, &data[0], len(data));
|
||||
var bytes_written = unix_write(fd, &data[0], len(data));
|
||||
if(bytes_written == -1) {
|
||||
return 0, 1;
|
||||
}
|
||||
return bytes_written, 0;
|
||||
}
|
||||
|
||||
read :: proc(fd: Handle, data: []u8) -> (AddressSize, Errno) {
|
||||
const read = proc(fd: Handle, data: []u8) -> (AddressSize, Errno) {
|
||||
assert(fd != -1);
|
||||
|
||||
bytes_read := unix_read(fd, &data[0], len(data));
|
||||
var bytes_read = unix_read(fd, &data[0], len(data));
|
||||
if(bytes_read == -1) {
|
||||
return 0, 1;
|
||||
}
|
||||
return bytes_read, 0;
|
||||
}
|
||||
|
||||
seek :: proc(fd: Handle, offset: AddressSize, whence: int) -> (AddressSize, Errno) {
|
||||
const seek = proc(fd: Handle, offset: AddressSize, whence: int) -> (AddressSize, Errno) {
|
||||
assert(fd != -1);
|
||||
|
||||
final_offset := unix_lseek(fd, offset, whence);
|
||||
var final_offset = unix_lseek(fd, offset, whence);
|
||||
if(final_offset == -1) {
|
||||
return 0, 1;
|
||||
}
|
||||
return final_offset, 0;
|
||||
}
|
||||
|
||||
file_size :: proc(fd: Handle) -> (i64, Errno) {
|
||||
prev, _ := seek(fd, 0, SEEK_CUR);
|
||||
size, err := seek(fd, 0, SEEK_END);
|
||||
const file_size = proc(fd: Handle) -> (i64, Errno) {
|
||||
var prev, _ = seek(fd, 0, SEEK_CUR);
|
||||
var size, err = seek(fd, 0, SEEK_END);
|
||||
seek(fd, prev, SEEK_SET);
|
||||
return size, err;
|
||||
}
|
||||
@@ -206,81 +206,43 @@ file_size :: proc(fd: Handle) -> (i64, Errno) {
|
||||
|
||||
|
||||
// NOTE(bill): Uses startup to initialize it
|
||||
stdin: Handle = 0; // get_std_handle(win32.STD_INPUT_HANDLE);
|
||||
stdout: Handle = 1; // get_std_handle(win32.STD_OUTPUT_HANDLE);
|
||||
stderr: Handle = 2; // get_std_handle(win32.STD_ERROR_HANDLE);
|
||||
var stdin: Handle = 0; // get_std_handle(win32.STD_INPUT_HANDLE);
|
||||
var stdout: Handle = 1; // get_std_handle(win32.STD_OUTPUT_HANDLE);
|
||||
var stderr: Handle = 2; // get_std_handle(win32.STD_ERROR_HANDLE);
|
||||
|
||||
/* TODO(zangent): Implement these!
|
||||
last_write_time :: proc(fd: Handle) -> FileTime {}
|
||||
last_write_time_by_name :: proc(name: string) -> FileTime {}
|
||||
const last_write_time = proc(fd: Handle) -> FileTime {}
|
||||
const last_write_time_by_name = proc(name: string) -> FileTime {}
|
||||
*/
|
||||
|
||||
stat :: proc(path: string) -> (Stat, bool) #inline {
|
||||
s: Stat;
|
||||
cstr := strings.new_c_string(path);
|
||||
const stat = proc(path: string) -> (Stat, bool) #inline {
|
||||
var s: Stat;
|
||||
var cstr = strings.new_c_string(path);
|
||||
defer free(cstr);
|
||||
ret_int := unix_stat(cstr, &s);
|
||||
var ret_int = unix_stat(cstr, &s);
|
||||
return s, ret_int==0;
|
||||
}
|
||||
|
||||
access :: proc(path: string, mask: int) -> bool #inline {
|
||||
cstr := strings.new_c_string(path);
|
||||
const access = proc(path: string, mask: int) -> bool #inline {
|
||||
var cstr = strings.new_c_string(path);
|
||||
defer free(cstr);
|
||||
return unix_access(cstr, mask) == 0;
|
||||
}
|
||||
|
||||
// read_entire_file :: proc(name: string) -> ([]u8, bool) {
|
||||
|
||||
// handle, err := open_simple(name, O_RDONLY);
|
||||
// if(err != 0) {
|
||||
// fmt.println("Failed to open file.");
|
||||
// return nil, false;
|
||||
// }
|
||||
// defer(close(handle));
|
||||
|
||||
// // We have a file!
|
||||
|
||||
// size: AddressSize;
|
||||
// size, err = seek(handle, 0, SEEK_END);
|
||||
// if(err != 0) {
|
||||
// fmt.println("Failed to seek to end of file.");
|
||||
// return nil, false;
|
||||
// }
|
||||
|
||||
// _, err = seek(handle, 0, SEEK_SET);
|
||||
// if(err != 0) {
|
||||
// fmt.println("Failed to seek to beginning of file.");
|
||||
// return nil, false;
|
||||
// }
|
||||
|
||||
// // We have a file size!
|
||||
|
||||
// data := make([]u8, size+1);
|
||||
// if data == nil {
|
||||
// fmt.println("Failed to allocate file buffer.");
|
||||
// return nil, false;
|
||||
// }
|
||||
|
||||
// read(handle, data);
|
||||
// data[size] = 0;
|
||||
|
||||
// return data, true;
|
||||
// }
|
||||
|
||||
heap_alloc :: proc(size: int) -> rawptr #inline {
|
||||
const heap_alloc = proc(size: int) -> rawptr #inline {
|
||||
assert(size > 0);
|
||||
return unix_malloc(size);
|
||||
}
|
||||
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr #inline {
|
||||
const heap_resize = proc(ptr: rawptr, new_size: int) -> rawptr #inline {
|
||||
return unix_realloc(ptr, new_size);
|
||||
}
|
||||
heap_free :: proc(ptr: rawptr) #inline {
|
||||
const heap_free = proc(ptr: rawptr) #inline {
|
||||
unix_free(ptr);
|
||||
}
|
||||
|
||||
getenv :: proc(name: string) -> (string, bool) {
|
||||
path_str := strings.new_c_string(name);
|
||||
cstr: ^u8 = unix_getenv(path_str);
|
||||
const getenv = proc(name: string) -> (string, bool) {
|
||||
var path_str = strings.new_c_string(name);
|
||||
var cstr: ^u8 = unix_getenv(path_str);
|
||||
free(path_str);
|
||||
if(cstr == nil) {
|
||||
return "", false;
|
||||
@@ -288,33 +250,33 @@ getenv :: proc(name: string) -> (string, bool) {
|
||||
return strings.to_odin_string(cstr), true;
|
||||
}
|
||||
|
||||
exit :: proc(code: int) #inline {
|
||||
const exit = proc(code: int) #inline {
|
||||
unix_exit(code);
|
||||
}
|
||||
|
||||
|
||||
current_thread_id :: proc() -> int {
|
||||
const current_thread_id = proc() -> int {
|
||||
// return cast(int) unix_gettid();
|
||||
return 0;
|
||||
}
|
||||
|
||||
dlopen :: proc(filename: string, flags: int) -> rawptr #inline {
|
||||
cstr := strings.new_c_string(filename);
|
||||
handle := unix_dlopen(cstr, flags);
|
||||
const dlopen = proc(filename: string, flags: int) -> rawptr #inline {
|
||||
var cstr = strings.new_c_string(filename);
|
||||
var handle = unix_dlopen(cstr, flags);
|
||||
free(cstr);
|
||||
return handle;
|
||||
}
|
||||
dlsym :: proc(handle: rawptr, symbol: string) -> (proc() #cc_c) #inline {
|
||||
const dlsym = proc(handle: rawptr, symbol: string) -> (proc() #cc_c) #inline {
|
||||
assert(handle != nil);
|
||||
cstr := strings.new_c_string(symbol);
|
||||
proc_handle := unix_dlsym(handle, cstr);
|
||||
var cstr = strings.new_c_string(symbol);
|
||||
var proc_handle = unix_dlsym(handle, cstr);
|
||||
free(cstr);
|
||||
return proc_handle;
|
||||
}
|
||||
dlclose :: proc(handle: rawptr) -> bool #inline {
|
||||
const dlclose = proc(handle: rawptr) -> bool #inline {
|
||||
assert(handle != nil);
|
||||
return unix_dlclose(handle) == 0;
|
||||
}
|
||||
dlerror :: proc() -> string {
|
||||
const dlerror = proc() -> string {
|
||||
return strings.to_odin_string(unix_dlerror());
|
||||
}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
Any :: struct #ordered {
|
||||
const Any = struct #ordered {
|
||||
data: rawptr,
|
||||
type_info: ^TypeInfo,
|
||||
}
|
||||
|
||||
String :: struct #ordered {
|
||||
const String = struct #ordered {
|
||||
data: ^u8,
|
||||
len: int,
|
||||
};
|
||||
|
||||
Slice :: struct #ordered {
|
||||
const Slice = struct #ordered {
|
||||
data: rawptr,
|
||||
len: int,
|
||||
cap: int,
|
||||
};
|
||||
|
||||
DynamicArray :: struct #ordered {
|
||||
const DynamicArray = struct #ordered {
|
||||
data: rawptr,
|
||||
len: int,
|
||||
cap: int,
|
||||
allocator: Allocator,
|
||||
};
|
||||
|
||||
DynamicMap :: struct #ordered {
|
||||
const DynamicMap = struct #ordered {
|
||||
hashes: [dynamic]int,
|
||||
entries: DynamicArray,
|
||||
};
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#import . "decimal.odin";
|
||||
|
||||
IntFlag :: enum {
|
||||
const IntFlag = enum {
|
||||
Prefix = 1<<0,
|
||||
Plus = 1<<1,
|
||||
Space = 1<<2,
|
||||
}
|
||||
|
||||
|
||||
parse_bool :: proc(s: string) -> (result: bool, ok: bool) {
|
||||
const parse_bool = proc(s: string) -> (result: bool, ok: bool) {
|
||||
match s {
|
||||
case "1", "t", "T", "true", "TRUE", "True":
|
||||
return true, true;
|
||||
@@ -17,9 +17,9 @@ parse_bool :: proc(s: string) -> (result: bool, ok: bool) {
|
||||
return false, false;
|
||||
}
|
||||
|
||||
_digit_value :: proc(r: rune) -> (int) {
|
||||
ri := int(r);
|
||||
v: int = 16;
|
||||
const _digit_value = proc(r: rune) -> (int) {
|
||||
var ri = int(r);
|
||||
var v: int = 16;
|
||||
match r {
|
||||
case '0'..'9': v = ri-'0';
|
||||
case 'a'..'z': v = ri-'a'+10;
|
||||
@@ -28,8 +28,8 @@ _digit_value :: proc(r: rune) -> (int) {
|
||||
return v;
|
||||
}
|
||||
|
||||
parse_i128 :: proc(s: string) -> i128 {
|
||||
neg := false;
|
||||
const parse_i128 = proc(s: string) -> i128 {
|
||||
var neg = false;
|
||||
if len(s) > 1 {
|
||||
match s[0] {
|
||||
case '-':
|
||||
@@ -41,7 +41,7 @@ parse_i128 :: proc(s: string) -> i128 {
|
||||
}
|
||||
|
||||
|
||||
base: i128 = 10;
|
||||
var base: i128 = 10;
|
||||
if len(s) > 2 && s[0] == '0' {
|
||||
match s[1] {
|
||||
case 'b': base = 2; s = s[2..];
|
||||
@@ -53,13 +53,13 @@ parse_i128 :: proc(s: string) -> i128 {
|
||||
}
|
||||
|
||||
|
||||
value: i128;
|
||||
var value: i128;
|
||||
for r in s {
|
||||
if r == '_' {
|
||||
continue;
|
||||
}
|
||||
|
||||
v := i128(_digit_value(r));
|
||||
var v = i128(_digit_value(r));
|
||||
if v >= base {
|
||||
break;
|
||||
}
|
||||
@@ -70,14 +70,14 @@ parse_i128 :: proc(s: string) -> i128 {
|
||||
return neg ? -value : value;
|
||||
}
|
||||
|
||||
parse_u128 :: proc(s: string) -> u128 {
|
||||
neg := false;
|
||||
const parse_u128 = proc(s: string) -> u128 {
|
||||
var neg = false;
|
||||
if len(s) > 1 && s[0] == '+' {
|
||||
s = s[1..];
|
||||
}
|
||||
|
||||
|
||||
base: = u128(10);
|
||||
var base = u128(10);
|
||||
if len(s) > 2 && s[0] == '0' {
|
||||
match s[1] {
|
||||
case 'b': base = 2; s = s[2..];
|
||||
@@ -89,13 +89,13 @@ parse_u128 :: proc(s: string) -> u128 {
|
||||
}
|
||||
|
||||
|
||||
value: u128;
|
||||
var value: u128;
|
||||
for r in s {
|
||||
if r == '_' {
|
||||
continue;
|
||||
}
|
||||
|
||||
v := u128(_digit_value(r));
|
||||
var v = u128(_digit_value(r));
|
||||
if v >= base {
|
||||
break;
|
||||
}
|
||||
@@ -107,29 +107,29 @@ parse_u128 :: proc(s: string) -> u128 {
|
||||
}
|
||||
|
||||
|
||||
parse_int :: proc(s: string) -> int {
|
||||
const parse_int = proc(s: string) -> int {
|
||||
return int(parse_i128(s));
|
||||
}
|
||||
parse_uint :: proc(s: string, base: int) -> uint {
|
||||
const parse_uint = proc(s: string, base: int) -> uint {
|
||||
return uint(parse_u128(s));
|
||||
}
|
||||
|
||||
parse_f64 :: proc(s: string) -> f64 {
|
||||
i := 0;
|
||||
const parse_f64 = proc(s: string) -> f64 {
|
||||
var i = 0;
|
||||
|
||||
sign: f64 = 1;
|
||||
var sign: f64 = 1;
|
||||
match s[i] {
|
||||
case '-': i++; sign = -1;
|
||||
case '+': i++;
|
||||
}
|
||||
|
||||
value: f64 = 0;
|
||||
var value: f64 = 0;
|
||||
for ; i < len(s); i++ {
|
||||
r := rune(s[i]);
|
||||
var r = rune(s[i]);
|
||||
if r == '_' {
|
||||
continue;
|
||||
}
|
||||
v := _digit_value(r);
|
||||
var v = _digit_value(r);
|
||||
if v >= 10 {
|
||||
break;
|
||||
}
|
||||
@@ -138,15 +138,15 @@ parse_f64 :: proc(s: string) -> f64 {
|
||||
}
|
||||
|
||||
if s[i] == '.' {
|
||||
pow10: f64 = 10;
|
||||
var pow10: f64 = 10;
|
||||
i++;
|
||||
|
||||
for ; i < len(s); i++ {
|
||||
r := rune(s[i]);
|
||||
var r = rune(s[i]);
|
||||
if r == '_' {
|
||||
continue;
|
||||
}
|
||||
v := _digit_value(r);
|
||||
var v = _digit_value(r);
|
||||
if v >= 10 {
|
||||
break;
|
||||
}
|
||||
@@ -155,8 +155,8 @@ parse_f64 :: proc(s: string) -> f64 {
|
||||
}
|
||||
}
|
||||
|
||||
frac := false;
|
||||
scale: f64 = 1;
|
||||
var frac = false;
|
||||
var scale: f64 = 1;
|
||||
|
||||
if s[i] == 'e' || s[i] == 'E' {
|
||||
i++;
|
||||
@@ -166,13 +166,13 @@ parse_f64 :: proc(s: string) -> f64 {
|
||||
case '+': i++;
|
||||
}
|
||||
|
||||
exp: u32 = 0;
|
||||
var exp: u32 = 0;
|
||||
for ; i < len(s); i++ {
|
||||
r := rune(s[i]);
|
||||
var r = rune(s[i]);
|
||||
if r == '_' {
|
||||
continue;
|
||||
}
|
||||
d := u32(_digit_value(r));
|
||||
var d = u32(_digit_value(r));
|
||||
if d >= 10 {
|
||||
break;
|
||||
}
|
||||
@@ -189,48 +189,48 @@ parse_f64 :: proc(s: string) -> f64 {
|
||||
}
|
||||
|
||||
|
||||
append_bool :: proc(buf: []u8, b: bool) -> string {
|
||||
s := b ? "true" : "false";
|
||||
const append_bool = proc(buf: []u8, b: bool) -> string {
|
||||
var s = b ? "true" : "false";
|
||||
append(buf, ..[]u8(s));
|
||||
return string(buf);
|
||||
}
|
||||
|
||||
append_uint :: proc(buf: []u8, u: u64, base: int) -> string {
|
||||
const append_uint = proc(buf: []u8, u: u64, base: int) -> string {
|
||||
return append_bits(buf, u128(u), base, false, 8*size_of(uint), digits, 0);
|
||||
}
|
||||
append_int :: proc(buf: []u8, i: i64, base: int) -> string {
|
||||
const append_int = proc(buf: []u8, i: i64, base: int) -> string {
|
||||
return append_bits(buf, u128(i), base, true, 8*size_of(int), digits, 0);
|
||||
}
|
||||
itoa :: proc(buf: []u8, i: int) -> string { return append_int(buf, i64(i), 10); }
|
||||
const itoa = proc(buf: []u8, i: int) -> string { return append_int(buf, i64(i), 10); }
|
||||
|
||||
append_float :: proc(buf: []u8, f: f64, fmt: u8, prec, bit_size: int) -> string {
|
||||
const append_float = proc(buf: []u8, f: f64, fmt: u8, prec, bit_size: int) -> string {
|
||||
return string(generic_ftoa(buf, f, fmt, prec, bit_size));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
DecimalSlice :: struct {
|
||||
const DecimalSlice = struct {
|
||||
digits: []u8,
|
||||
count: int,
|
||||
decimal_point: int,
|
||||
neg: bool,
|
||||
}
|
||||
|
||||
Float_Info :: struct {
|
||||
const Float_Info = struct {
|
||||
mantbits: uint,
|
||||
expbits: uint,
|
||||
bias: int,
|
||||
}
|
||||
|
||||
_f16_info := Float_Info{10, 5, -15};
|
||||
_f32_info := Float_Info{23, 8, -127};
|
||||
_f64_info := Float_Info{52, 11, -1023};
|
||||
var _f16_info = Float_Info{10, 5, -15};
|
||||
var _f32_info = Float_Info{23, 8, -127};
|
||||
var _f64_info = Float_Info{52, 11, -1023};
|
||||
|
||||
|
||||
generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8 {
|
||||
bits: u64;
|
||||
flt: ^Float_Info;
|
||||
const generic_ftoa = proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8 {
|
||||
var bits: u64;
|
||||
var flt: ^Float_Info;
|
||||
match bit_size {
|
||||
case 32:
|
||||
bits = u64(transmute(u32, f32(val)));
|
||||
@@ -242,13 +242,13 @@ generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8
|
||||
panic("strconv: invalid bit_size");
|
||||
}
|
||||
|
||||
neg := bits>>(flt.expbits+flt.mantbits) != 0;
|
||||
exp := int(bits>>flt.mantbits) & (1<<flt.expbits - 1);
|
||||
mant := bits & (u64(1) << flt.mantbits - 1);
|
||||
var neg = bits>>(flt.expbits+flt.mantbits) != 0;
|
||||
var exp = int(bits>>flt.mantbits) & (1<<flt.expbits - 1);
|
||||
var mant = bits & (u64(1) << flt.mantbits - 1);
|
||||
|
||||
match exp {
|
||||
case 1<<flt.expbits - 1:
|
||||
s: string;
|
||||
var s: string;
|
||||
if mant != 0 {
|
||||
s = "NaN";
|
||||
} else if neg {
|
||||
@@ -268,12 +268,12 @@ generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8
|
||||
|
||||
exp += flt.bias;
|
||||
|
||||
d_: Decimal;
|
||||
d := &d_;
|
||||
var d_: Decimal;
|
||||
var d = &d_;
|
||||
assign(d, mant);
|
||||
shift(d, exp - int(flt.mantbits));
|
||||
digs: DecimalSlice;
|
||||
shortest := prec < 0;
|
||||
var digs: DecimalSlice;
|
||||
var shortest = prec < 0;
|
||||
if shortest {
|
||||
round_shortest(d, mant, exp, flt);
|
||||
digs = DecimalSlice{digits = d.digits[..], count = d.count, decimal_point = d.decimal_point};
|
||||
@@ -300,14 +300,14 @@ generic_ftoa :: proc(buf: []u8, val: f64, fmt: u8, prec, bit_size: int) -> []u8
|
||||
|
||||
|
||||
|
||||
format_digits :: proc(buf: []u8, shortest: bool, neg: bool, digs: DecimalSlice, prec: int, fmt: u8) -> []u8 {
|
||||
const format_digits = proc(buf: []u8, shortest: bool, neg: bool, digs: DecimalSlice, prec: int, fmt: u8) -> []u8 {
|
||||
match fmt {
|
||||
case 'f', 'F':
|
||||
append(buf, neg ? '-' : '+');
|
||||
|
||||
// integer, padded with zeros when needed
|
||||
if digs.decimal_point > 0 {
|
||||
m := min(digs.count, digs.decimal_point);
|
||||
var m = min(digs.count, digs.decimal_point);
|
||||
append(buf, ..digs.digits[0..<m]);
|
||||
for ; m < digs.decimal_point; m++ {
|
||||
append(buf, '0');
|
||||
@@ -321,8 +321,8 @@ format_digits :: proc(buf: []u8, shortest: bool, neg: bool, digs: DecimalSlice,
|
||||
if prec > 0 {
|
||||
append(buf, '.');
|
||||
for i in 0..<prec {
|
||||
c: u8 = '0';
|
||||
if j := digs.decimal_point + i; 0 <= j && j < digs.count {
|
||||
var c: u8 = '0';
|
||||
if var j = digs.decimal_point + i; 0 <= j && j < digs.count {
|
||||
c = digs.digits[j];
|
||||
}
|
||||
append(buf, c);
|
||||
@@ -340,14 +340,14 @@ format_digits :: proc(buf: []u8, shortest: bool, neg: bool, digs: DecimalSlice,
|
||||
return buf; // TODO
|
||||
}
|
||||
|
||||
c: [2]u8;
|
||||
var c: [2]u8;
|
||||
c[0] = '%';
|
||||
c[1] = fmt;
|
||||
append(buf, ..c[..]);
|
||||
return buf;
|
||||
}
|
||||
|
||||
round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) {
|
||||
const round_shortest = proc(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) {
|
||||
if mant == 0 { // If mantissa is zero, the number is zero
|
||||
d.count = 0;
|
||||
return;
|
||||
@@ -359,18 +359,18 @@ round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) {
|
||||
log(2) >~ 0.332
|
||||
332*(dp-nd) >= 100*(exp-mantbits)
|
||||
*/
|
||||
minexp := flt.bias+1;
|
||||
var minexp = flt.bias+1;
|
||||
if exp > minexp && 332*(d.decimal_point-d.count) >= 100*(exp - int(flt.mantbits)) {
|
||||
// Number is already its shortest
|
||||
return;
|
||||
}
|
||||
|
||||
upper_: Decimal; upper: = &upper_;
|
||||
var upper_: Decimal; var upper = &upper_;
|
||||
assign(upper, 2*mant - 1);
|
||||
shift(upper, exp - int(flt.mantbits) - 1);
|
||||
|
||||
mantlo: u64;
|
||||
explo: int;
|
||||
var mantlo: u64;
|
||||
var explo: int;
|
||||
if mant > 1<<flt.mantbits || exp == minexp {
|
||||
mantlo = mant-1;
|
||||
explo = exp;
|
||||
@@ -378,25 +378,25 @@ round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) {
|
||||
mantlo = 2*mant - 1;
|
||||
explo = exp-1;
|
||||
}
|
||||
lower_: Decimal; lower: = &lower_;
|
||||
var lower_: Decimal; var lower = &lower_;
|
||||
assign(lower, 2*mantlo + 1);
|
||||
shift(lower, explo - int(flt.mantbits) - 1);
|
||||
|
||||
inclusive := mant%2 == 0;
|
||||
var inclusive = mant%2 == 0;
|
||||
|
||||
for i in 0..<d.count {
|
||||
l: u8 = '0'; // lower digit
|
||||
var l: u8 = '0'; // lower digit
|
||||
if i < lower.count {
|
||||
l = lower.digits[i];
|
||||
}
|
||||
m := d.digits[i]; // middle digit
|
||||
u: u8 = '0'; // upper digit
|
||||
var m = d.digits[i]; // middle digit
|
||||
var u: u8 = '0'; // upper digit
|
||||
if i < upper.count {
|
||||
u = upper.digits[i];
|
||||
}
|
||||
|
||||
ok_round_down := l != m || inclusive && i+1 == lower.count;
|
||||
ok_round_up := m != u && (inclusive || m+1 < u || i+1 < upper.count);
|
||||
var ok_round_down = l != m || inclusive && i+1 == lower.count;
|
||||
var ok_round_up = m != u && (inclusive || m+1 < u || i+1 < upper.count);
|
||||
|
||||
if (ok_round_down && ok_round_up) {
|
||||
round(d, i+1);
|
||||
@@ -414,36 +414,36 @@ round_shortest :: proc(d: ^Decimal, mant: u64, exp: int, flt: ^Float_Info) {
|
||||
|
||||
}
|
||||
|
||||
MAX_BASE :: 32;
|
||||
immutable digits := "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
const MAX_BASE = 32;
|
||||
immutable var digits = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
|
||||
is_integer_negative :: proc(u: u128, is_signed: bool, bit_size: int) -> (unsigned: u128, neg: bool) {
|
||||
neg := false;
|
||||
const is_integer_negative = proc(u: u128, is_signed: bool, bit_size: int) -> (unsigned: u128, neg: bool) {
|
||||
var neg = false;
|
||||
if is_signed {
|
||||
match bit_size {
|
||||
case 8:
|
||||
i := i8(u);
|
||||
var i = i8(u);
|
||||
neg = i < 0;
|
||||
if neg { i = -i; }
|
||||
u = u128(i);
|
||||
case 16:
|
||||
i := i16(u);
|
||||
var i = i16(u);
|
||||
neg = i < 0;
|
||||
if neg { i = -i; }
|
||||
u = u128(i);
|
||||
case 32:
|
||||
i := i32(u);
|
||||
var i = i32(u);
|
||||
neg = i < 0;
|
||||
if neg { i = -i; }
|
||||
u = u128(i);
|
||||
case 64:
|
||||
i := i64(u);
|
||||
var i = i64(u);
|
||||
neg = i < 0;
|
||||
if neg { i = -i; }
|
||||
u = u128(i);
|
||||
case 128:
|
||||
i := i128(u);
|
||||
var i = i128(u);
|
||||
neg = i < 0;
|
||||
if neg { i = -i; }
|
||||
u = u128(i);
|
||||
@@ -454,15 +454,15 @@ is_integer_negative :: proc(u: u128, is_signed: bool, bit_size: int) -> (unsigne
|
||||
return u, neg;
|
||||
}
|
||||
|
||||
append_bits :: proc(buf: []u8, u_: u128, base: int, is_signed: bool, bit_size: int, digits: string, flags: IntFlag) -> string {
|
||||
const append_bits = proc(buf: []u8, u_: u128, base: int, is_signed: bool, bit_size: int, digits: string, flags: IntFlag) -> string {
|
||||
if base < 2 || base > MAX_BASE {
|
||||
panic("strconv: illegal base passed to append_bits");
|
||||
}
|
||||
|
||||
a: [129]u8;
|
||||
i := len(a);
|
||||
u, neg := is_integer_negative(u_, is_signed, bit_size);
|
||||
b := u128(base);
|
||||
var a: [129]u8;
|
||||
var i = len(a);
|
||||
var u, neg = is_integer_negative(u_, is_signed, bit_size);
|
||||
var b = u128(base);
|
||||
for u >= b {
|
||||
i--; a[i] = digits[uint(u % b)];
|
||||
u /= b;
|
||||
@@ -470,7 +470,7 @@ append_bits :: proc(buf: []u8, u_: u128, base: int, is_signed: bool, bit_size: i
|
||||
i--; a[i] = digits[uint(u % b)];
|
||||
|
||||
if flags&IntFlag.Prefix != 0 {
|
||||
ok := true;
|
||||
var ok = true;
|
||||
match base {
|
||||
case 2: i--; a[i] = 'b';
|
||||
case 8: i--; a[i] = 'o';
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
new_c_string :: proc(s: string) -> ^u8 {
|
||||
c := make([]u8, len(s)+1);
|
||||
const new_c_string = proc(s: string) -> ^u8 {
|
||||
var c = make([]u8, len(s)+1);
|
||||
copy(c, []u8(s));
|
||||
c[len(s)] = 0;
|
||||
return &c[0];
|
||||
}
|
||||
|
||||
to_odin_string :: proc(c: ^u8) -> string {
|
||||
len := 0;
|
||||
const to_odin_string = proc(c: ^u8) -> string {
|
||||
var len = 0;
|
||||
for (c+len)^ != 0 {
|
||||
len++;
|
||||
}
|
||||
|
||||
@@ -1,53 +1,53 @@
|
||||
#import "atomics.odin";
|
||||
#import "os.odin";
|
||||
|
||||
Semaphore :: struct {
|
||||
const Semaphore = struct {
|
||||
// _handle: win32.Handle,
|
||||
}
|
||||
|
||||
Mutex :: struct {
|
||||
const Mutex = struct {
|
||||
_semaphore: Semaphore,
|
||||
_counter: i32,
|
||||
_owner: i32,
|
||||
_recursion: i32,
|
||||
}
|
||||
|
||||
current_thread_id :: proc() -> i32 {
|
||||
const current_thread_id = proc() -> i32 {
|
||||
return i32(os.current_thread_id());
|
||||
}
|
||||
|
||||
semaphore_init :: proc(s: ^Semaphore) {
|
||||
const semaphore_init = proc(s: ^Semaphore) {
|
||||
// s._handle = win32.CreateSemaphoreA(nil, 0, 1<<31-1, nil);
|
||||
}
|
||||
|
||||
semaphore_destroy :: proc(s: ^Semaphore) {
|
||||
const semaphore_destroy = proc(s: ^Semaphore) {
|
||||
// win32.CloseHandle(s._handle);
|
||||
}
|
||||
|
||||
semaphore_post :: proc(s: ^Semaphore, count: int) {
|
||||
const semaphore_post = proc(s: ^Semaphore, count: int) {
|
||||
// win32.ReleaseSemaphore(s._handle, cast(i32)count, nil);
|
||||
}
|
||||
|
||||
semaphore_release :: proc(s: ^Semaphore) #inline {
|
||||
const semaphore_release = proc(s: ^Semaphore) #inline {
|
||||
semaphore_post(s, 1);
|
||||
}
|
||||
|
||||
semaphore_wait :: proc(s: ^Semaphore) {
|
||||
const semaphore_wait = proc(s: ^Semaphore) {
|
||||
// win32.WaitForSingleObject(s._handle, win32.INFINITE);
|
||||
}
|
||||
|
||||
|
||||
mutex_init :: proc(m: ^Mutex) {
|
||||
const mutex_init = proc(m: ^Mutex) {
|
||||
atomics.store(&m._counter, 0);
|
||||
atomics.store(&m._owner, current_thread_id());
|
||||
semaphore_init(&m._semaphore);
|
||||
m._recursion = 0;
|
||||
}
|
||||
mutex_destroy :: proc(m: ^Mutex) {
|
||||
const mutex_destroy = proc(m: ^Mutex) {
|
||||
semaphore_destroy(&m._semaphore);
|
||||
}
|
||||
mutex_lock :: proc(m: ^Mutex) {
|
||||
thread_id := current_thread_id();
|
||||
const mutex_lock = proc(m: ^Mutex) {
|
||||
var thread_id = current_thread_id();
|
||||
if atomics.fetch_add(&m._counter, 1) > 0 {
|
||||
if thread_id != atomics.load(&m._owner) {
|
||||
semaphore_wait(&m._semaphore);
|
||||
@@ -56,12 +56,12 @@ mutex_lock :: proc(m: ^Mutex) {
|
||||
atomics.store(&m._owner, thread_id);
|
||||
m._recursion++;
|
||||
}
|
||||
mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||
thread_id := current_thread_id();
|
||||
const mutex_try_lock = proc(m: ^Mutex) -> bool {
|
||||
var thread_id = current_thread_id();
|
||||
if atomics.load(&m._owner) == thread_id {
|
||||
atomics.fetch_add(&m._counter, 1);
|
||||
} else {
|
||||
expected: i32 = 0;
|
||||
var expected: i32 = 0;
|
||||
if atomics.load(&m._counter) != 0 {
|
||||
return false;
|
||||
}
|
||||
@@ -73,9 +73,9 @@ mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||
m._recursion++;
|
||||
return true;
|
||||
}
|
||||
mutex_unlock :: proc(m: ^Mutex) {
|
||||
recursion: i32;
|
||||
thread_id := current_thread_id();
|
||||
const mutex_unlock = proc(m: ^Mutex) {
|
||||
var recursion: i32;
|
||||
var thread_id = current_thread_id();
|
||||
assert(thread_id == atomics.load(&m._owner));
|
||||
|
||||
m._recursion--;
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
#import win32 "sys/windows.odin" when ODIN_OS == "windows";
|
||||
#import "atomics.odin";
|
||||
|
||||
Semaphore :: struct {
|
||||
const Semaphore = struct {
|
||||
_handle: win32.Handle,
|
||||
}
|
||||
|
||||
Mutex :: struct {
|
||||
const Mutex = struct {
|
||||
_semaphore: Semaphore,
|
||||
_counter: i32,
|
||||
_owner: i32,
|
||||
_recursion: i32,
|
||||
}
|
||||
|
||||
current_thread_id :: proc() -> i32 {
|
||||
const current_thread_id = proc() -> i32 {
|
||||
return i32(win32.get_current_thread_id());
|
||||
}
|
||||
|
||||
semaphore_init :: proc(s: ^Semaphore) {
|
||||
const semaphore_init = proc(s: ^Semaphore) {
|
||||
s._handle = win32.create_semaphore_a(nil, 0, 1<<31-1, nil);
|
||||
}
|
||||
|
||||
semaphore_destroy :: proc(s: ^Semaphore) {
|
||||
const semaphore_destroy = proc(s: ^Semaphore) {
|
||||
win32.close_handle(s._handle);
|
||||
}
|
||||
|
||||
semaphore_post :: proc(s: ^Semaphore, count: int) {
|
||||
const semaphore_post = proc(s: ^Semaphore, count: int) {
|
||||
win32.release_semaphore(s._handle, i32(count), nil);
|
||||
}
|
||||
|
||||
semaphore_release :: proc(s: ^Semaphore) #inline { semaphore_post(s, 1); }
|
||||
const semaphore_release = proc(s: ^Semaphore) #inline { semaphore_post(s, 1); }
|
||||
|
||||
semaphore_wait :: proc(s: ^Semaphore) {
|
||||
const semaphore_wait = proc(s: ^Semaphore) {
|
||||
win32.wait_for_single_object(s._handle, win32.INFINITE);
|
||||
}
|
||||
|
||||
|
||||
mutex_init :: proc(m: ^Mutex) {
|
||||
const mutex_init = proc(m: ^Mutex) {
|
||||
atomics.store(&m._counter, 0);
|
||||
atomics.store(&m._owner, current_thread_id());
|
||||
semaphore_init(&m._semaphore);
|
||||
m._recursion = 0;
|
||||
}
|
||||
mutex_destroy :: proc(m: ^Mutex) {
|
||||
const mutex_destroy = proc(m: ^Mutex) {
|
||||
semaphore_destroy(&m._semaphore);
|
||||
}
|
||||
mutex_lock :: proc(m: ^Mutex) {
|
||||
thread_id := current_thread_id();
|
||||
const mutex_lock = proc(m: ^Mutex) {
|
||||
var thread_id = current_thread_id();
|
||||
if atomics.fetch_add(&m._counter, 1) > 0 {
|
||||
if thread_id != atomics.load(&m._owner) {
|
||||
semaphore_wait(&m._semaphore);
|
||||
@@ -54,12 +54,12 @@ mutex_lock :: proc(m: ^Mutex) {
|
||||
atomics.store(&m._owner, thread_id);
|
||||
m._recursion++;
|
||||
}
|
||||
mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||
thread_id := current_thread_id();
|
||||
const mutex_try_lock = proc(m: ^Mutex) -> bool {
|
||||
var thread_id = current_thread_id();
|
||||
if atomics.load(&m._owner) == thread_id {
|
||||
atomics.fetch_add(&m._counter, 1);
|
||||
} else {
|
||||
expected: i32 = 0;
|
||||
var expected: i32 = 0;
|
||||
if atomics.load(&m._counter) != 0 {
|
||||
return false;
|
||||
}
|
||||
@@ -71,9 +71,9 @@ mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||
m._recursion++;
|
||||
return true;
|
||||
}
|
||||
mutex_unlock :: proc(m: ^Mutex) {
|
||||
recursion: i32;
|
||||
thread_id := current_thread_id();
|
||||
const mutex_unlock = proc(m: ^Mutex) {
|
||||
var recursion: i32;
|
||||
var thread_id = current_thread_id();
|
||||
assert(thread_id == atomics.load(&m._owner));
|
||||
|
||||
m._recursion--;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
#foreign_system_library "opengl32.lib" when ODIN_OS == "windows";
|
||||
#import . "windows.odin";
|
||||
|
||||
CONTEXT_MAJOR_VERSION_ARB :: 0x2091;
|
||||
CONTEXT_MINOR_VERSION_ARB :: 0x2092;
|
||||
CONTEXT_FLAGS_ARB :: 0x2094;
|
||||
CONTEXT_PROFILE_MASK_ARB :: 0x9126;
|
||||
CONTEXT_FORWARD_COMPATIBLE_BIT_ARB :: 0x0002;
|
||||
CONTEXT_CORE_PROFILE_BIT_ARB :: 0x00000001;
|
||||
CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x00000002;
|
||||
const CONTEXT_MAJOR_VERSION_ARB = 0x2091;
|
||||
const CONTEXT_MINOR_VERSION_ARB = 0x2092;
|
||||
const CONTEXT_FLAGS_ARB = 0x2094;
|
||||
const CONTEXT_PROFILE_MASK_ARB = 0x9126;
|
||||
const CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x0002;
|
||||
const CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001;
|
||||
const CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002;
|
||||
|
||||
Hglrc :: Handle;
|
||||
ColorRef :: u32;
|
||||
const Hglrc = Handle;
|
||||
const ColorRef = u32;
|
||||
|
||||
LayerPlaneDescriptor :: struct {
|
||||
const LayerPlaneDescriptor = struct {
|
||||
size: u16,
|
||||
version: u16,
|
||||
flags: u32,
|
||||
@@ -39,11 +39,11 @@ LayerPlaneDescriptor :: struct {
|
||||
transparent: ColorRef,
|
||||
}
|
||||
|
||||
PointFloat :: struct {
|
||||
const PointFloat = struct {
|
||||
x, y: f32,
|
||||
}
|
||||
|
||||
Glyph_MetricsFloat :: struct {
|
||||
const Glyph_MetricsFloat = struct {
|
||||
black_box_x: f32,
|
||||
black_box_y: f32,
|
||||
glyph_origin: PointFloat,
|
||||
@@ -51,32 +51,32 @@ Glyph_MetricsFloat :: struct {
|
||||
cell_inc_y: f32,
|
||||
}
|
||||
|
||||
CreateContextAttribsARBType :: #type proc(hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc;
|
||||
ChoosePixelFormatARBType :: #type proc(hdc: Hdc, attrib_i_list: ^i32, attrib_f_list: ^f32, max_formats: u32, formats: ^i32, num_formats : ^u32) -> Bool #cc_c;
|
||||
SwapIntervalEXTType :: #type proc(interval: i32) -> bool #cc_c;
|
||||
GetExtensionsStringARBType :: #type proc(Hdc) -> ^u8 #cc_c;
|
||||
const CreateContextAttribsARBType = type proc(hdc: Hdc, h_share_context: rawptr, attribList: ^i32) -> Hglrc;
|
||||
const ChoosePixelFormatARBType = type proc(hdc: Hdc, attrib_i_list: ^i32, attrib_f_list: ^f32, max_formats: u32, formats: ^i32, num_formats : ^u32) -> Bool #cc_c;
|
||||
const SwapIntervalEXTType = type proc(interval: i32) -> bool #cc_c;
|
||||
const GetExtensionsStringARBType = type proc(Hdc) -> ^u8 #cc_c;
|
||||
|
||||
|
||||
create_context_attribs_arb: CreateContextAttribsARBType;
|
||||
choose_pixel_format_arb: ChoosePixelFormatARBType;
|
||||
swap_interval_ext: SwapIntervalEXTType;
|
||||
get_extensions_string_arb: GetExtensionsStringARBType;
|
||||
var create_context_attribs_arb: CreateContextAttribsARBType;
|
||||
var choose_pixel_format_arb: ChoosePixelFormatARBType;
|
||||
var swap_interval_ext: SwapIntervalEXTType;
|
||||
var get_extensions_string_arb: GetExtensionsStringARBType;
|
||||
|
||||
|
||||
|
||||
create_context :: proc(hdc: Hdc) -> Hglrc #foreign opengl32 "wglCreateContext";
|
||||
make_current :: proc(hdc: Hdc, hglrc: Hglrc) -> Bool #foreign opengl32 "wglMakeCurrent";
|
||||
get_proc_address :: proc(c_str: ^u8) -> Proc #foreign opengl32 "wglGetProcAddress";
|
||||
delete_context :: proc(hglrc: Hglrc) -> Bool #foreign opengl32 "wglDeleteContext";
|
||||
copy_context :: proc(src, dst: Hglrc, mask: u32) -> Bool #foreign opengl32 "wglCopyContext";
|
||||
create_layer_context :: proc(hdc: Hdc, layer_plane: i32) -> Hglrc #foreign opengl32 "wglCreateLayerContext";
|
||||
describe_layer_plane :: proc(hdc: Hdc, pixel_format, layer_plane: i32, bytes: u32, pd: ^LayerPlaneDescriptor) -> Bool #foreign opengl32 "wglDescribeLayerPlane";
|
||||
get_current_context :: proc() -> Hglrc #foreign opengl32 "wglGetCurrentContext";
|
||||
get_current_dc :: proc() -> Hdc #foreign opengl32 "wglGetCurrentDC";
|
||||
get_layer_palette_entries :: proc(hdc: Hdc, layer_plane, start, entries: i32, cr: ^ColorRef) -> i32 #foreign opengl32 "wglGetLayerPaletteEntries";
|
||||
realize_layer_palette :: proc(hdc: Hdc, layer_plane: i32, realize: Bool) -> Bool #foreign opengl32 "wglRealizeLayerPalette";
|
||||
set_layer_palette_entries :: proc(hdc: Hdc, layer_plane, start, entries: i32, cr: ^ColorRef) -> i32 #foreign opengl32 "wglSetLayerPaletteEntries";
|
||||
share_lists :: proc(hglrc1, hglrc2: Hglrc) -> Bool #foreign opengl32 "wglShareLists";
|
||||
swap_layer_buffers :: proc(hdc: Hdc, planes: u32) -> Bool #foreign opengl32 "wglSwapLayerBuffers";
|
||||
use_font_bitmaps :: proc(hdc: Hdc, first, count, list_base: u32) -> Bool #foreign opengl32 "wglUseFontBitmaps";
|
||||
use_font_outlines :: proc(hdc: Hdc, first, count, list_base: u32, deviation, extrusion: f32, format: i32, gmf: ^Glyph_MetricsFloat) -> Bool #foreign opengl32 "wglUseFontOutlines";
|
||||
const create_context = proc(hdc: Hdc) -> Hglrc #foreign opengl32 "wglCreateContext";
|
||||
const make_current = proc(hdc: Hdc, hglrc: Hglrc) -> Bool #foreign opengl32 "wglMakeCurrent";
|
||||
const get_proc_address = proc(c_str: ^u8) -> Proc #foreign opengl32 "wglGetProcAddress";
|
||||
const delete_context = proc(hglrc: Hglrc) -> Bool #foreign opengl32 "wglDeleteContext";
|
||||
const copy_context = proc(src, dst: Hglrc, mask: u32) -> Bool #foreign opengl32 "wglCopyContext";
|
||||
const create_layer_context = proc(hdc: Hdc, layer_plane: i32) -> Hglrc #foreign opengl32 "wglCreateLayerContext";
|
||||
const describe_layer_plane = proc(hdc: Hdc, pixel_format, layer_plane: i32, bytes: u32, pd: ^LayerPlaneDescriptor) -> Bool #foreign opengl32 "wglDescribeLayerPlane";
|
||||
const get_current_context = proc() -> Hglrc #foreign opengl32 "wglGetCurrentContext";
|
||||
const get_current_dc = proc() -> Hdc #foreign opengl32 "wglGetCurrentDC";
|
||||
const get_layer_palette_entries = proc(hdc: Hdc, layer_plane, start, entries: i32, cr: ^ColorRef) -> i32 #foreign opengl32 "wglGetLayerPaletteEntries";
|
||||
const realize_layer_palette = proc(hdc: Hdc, layer_plane: i32, realize: Bool) -> Bool #foreign opengl32 "wglRealizeLayerPalette";
|
||||
const set_layer_palette_entries = proc(hdc: Hdc, layer_plane, start, entries: i32, cr: ^ColorRef) -> i32 #foreign opengl32 "wglSetLayerPaletteEntries";
|
||||
const share_lists = proc(hglrc1, hglrc2: Hglrc) -> Bool #foreign opengl32 "wglShareLists";
|
||||
const swap_layer_buffers = proc(hdc: Hdc, planes: u32) -> Bool #foreign opengl32 "wglSwapLayerBuffers";
|
||||
const use_font_bitmaps = proc(hdc: Hdc, first, count, list_base: u32) -> Bool #foreign opengl32 "wglUseFontBitmaps";
|
||||
const use_font_outlines = proc(hdc: Hdc, first, count, list_base: u32, deviation, extrusion: f32, format: i32, gmf: ^Glyph_MetricsFloat) -> Bool #foreign opengl32 "wglUseFontOutlines";
|
||||
|
||||
@@ -4,93 +4,93 @@
|
||||
#foreign_system_library "winmm.lib" when ODIN_OS == "windows";
|
||||
#foreign_system_library "shell32.lib" when ODIN_OS == "windows";
|
||||
|
||||
Handle :: rawptr;
|
||||
Hwnd :: Handle;
|
||||
Hdc :: Handle;
|
||||
Hinstance :: Handle;
|
||||
Hicon :: Handle;
|
||||
Hcursor :: Handle;
|
||||
Hmenu :: Handle;
|
||||
Hbrush :: Handle;
|
||||
Hgdiobj :: Handle;
|
||||
Hmodule :: Handle;
|
||||
Wparam :: uint;
|
||||
Lparam :: int;
|
||||
Lresult :: int;
|
||||
Bool :: i32;
|
||||
WndProc :: #type proc(Hwnd, u32, Wparam, Lparam) -> Lresult #cc_c;
|
||||
const Handle = rawptr;
|
||||
const Hwnd = Handle;
|
||||
const Hdc = Handle;
|
||||
const Hinstance = Handle;
|
||||
const Hicon = Handle;
|
||||
const Hcursor = Handle;
|
||||
const Hmenu = Handle;
|
||||
const Hbrush = Handle;
|
||||
const Hgdiobj = Handle;
|
||||
const Hmodule = Handle;
|
||||
const Wparam = uint;
|
||||
const Lparam = int;
|
||||
const Lresult = int;
|
||||
const Bool = i32;
|
||||
const WndProc = type proc(Hwnd, u32, Wparam, Lparam) -> Lresult #cc_c;
|
||||
|
||||
|
||||
INVALID_HANDLE :: Handle(~int(0));
|
||||
const INVALID_HANDLE = Handle(~int(0));
|
||||
|
||||
FALSE: Bool : 0;
|
||||
TRUE: Bool : 1;
|
||||
const FALSE: Bool = 0;
|
||||
const TRUE: Bool = 1;
|
||||
|
||||
CS_VREDRAW :: 0x0001;
|
||||
CS_HREDRAW :: 0x0002;
|
||||
CS_OWNDC :: 0x0020;
|
||||
CW_USEDEFAULT :: -0x80000000;
|
||||
const CS_VREDRAW = 0x0001;
|
||||
const CS_HREDRAW = 0x0002;
|
||||
const CS_OWNDC = 0x0020;
|
||||
const CW_USEDEFAULT = -0x80000000;
|
||||
|
||||
WS_OVERLAPPED :: 0;
|
||||
WS_MAXIMIZEBOX :: 0x00010000;
|
||||
WS_MINIMIZEBOX :: 0x00020000;
|
||||
WS_THICKFRAME :: 0x00040000;
|
||||
WS_SYSMENU :: 0x00080000;
|
||||
WS_BORDER :: 0x00800000;
|
||||
WS_CAPTION :: 0x00C00000;
|
||||
WS_VISIBLE :: 0x10000000;
|
||||
WS_POPUP :: 0x80000000;
|
||||
WS_OVERLAPPEDWINDOW :: WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
|
||||
WS_POPUPWINDOW :: WS_POPUP | WS_BORDER | WS_SYSMENU;
|
||||
const WS_OVERLAPPED = 0;
|
||||
const WS_MAXIMIZEBOX = 0x00010000;
|
||||
const WS_MINIMIZEBOX = 0x00020000;
|
||||
const WS_THICKFRAME = 0x00040000;
|
||||
const WS_SYSMENU = 0x00080000;
|
||||
const WS_BORDER = 0x00800000;
|
||||
const WS_CAPTION = 0x00C00000;
|
||||
const WS_VISIBLE = 0x10000000;
|
||||
const WS_POPUP = 0x80000000;
|
||||
const WS_OVERLAPPEDWINDOW = WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
|
||||
const WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU;
|
||||
|
||||
WM_DESTROY :: 0x0002;
|
||||
WM_SIZE :: 0x0005;
|
||||
WM_CLOSE :: 0x0010;
|
||||
WM_ACTIVATEAPP :: 0x001C;
|
||||
WM_QUIT :: 0x0012;
|
||||
WM_KEYDOWN :: 0x0100;
|
||||
WM_KEYUP :: 0x0101;
|
||||
WM_SIZING :: 0x0214;
|
||||
WM_SYSKEYDOWN :: 0x0104;
|
||||
WM_SYSKEYUP :: 0x0105;
|
||||
WM_WINDOWPOSCHANGED :: 0x0047;
|
||||
WM_SETCURSOR :: 0x0020;
|
||||
WM_CHAR :: 0x0102;
|
||||
WM_ACTIVATE :: 0x0006;
|
||||
WM_SETFOCUS :: 0x0007;
|
||||
WM_KILLFOCUS :: 0x0008;
|
||||
WM_USER :: 0x0400;
|
||||
const WM_DESTROY = 0x0002;
|
||||
const WM_SIZE = 0x0005;
|
||||
const WM_CLOSE = 0x0010;
|
||||
const WM_ACTIVATEAPP = 0x001C;
|
||||
const WM_QUIT = 0x0012;
|
||||
const WM_KEYDOWN = 0x0100;
|
||||
const WM_KEYUP = 0x0101;
|
||||
const WM_SIZING = 0x0214;
|
||||
const WM_SYSKEYDOWN = 0x0104;
|
||||
const WM_SYSKEYUP = 0x0105;
|
||||
const WM_WINDOWPOSCHANGED = 0x0047;
|
||||
const WM_SETCURSOR = 0x0020;
|
||||
const WM_CHAR = 0x0102;
|
||||
const WM_ACTIVATE = 0x0006;
|
||||
const WM_SETFOCUS = 0x0007;
|
||||
const WM_KILLFOCUS = 0x0008;
|
||||
const WM_USER = 0x0400;
|
||||
|
||||
WM_MOUSEWHEEL :: 0x020A;
|
||||
WM_MOUSEMOVE :: 0x0200;
|
||||
WM_LBUTTONDOWN :: 0x0201;
|
||||
WM_LBUTTONUP :: 0x0202;
|
||||
WM_LBUTTONDBLCLK :: 0x0203;
|
||||
WM_RBUTTONDOWN :: 0x0204;
|
||||
WM_RBUTTONUP :: 0x0205;
|
||||
WM_RBUTTONDBLCLK :: 0x0206;
|
||||
WM_MBUTTONDOWN :: 0x0207;
|
||||
WM_MBUTTONUP :: 0x0208;
|
||||
WM_MBUTTONDBLCLK :: 0x0209;
|
||||
const WM_MOUSEWHEEL = 0x020A;
|
||||
const WM_MOUSEMOVE = 0x0200;
|
||||
const WM_LBUTTONDOWN = 0x0201;
|
||||
const WM_LBUTTONUP = 0x0202;
|
||||
const WM_LBUTTONDBLCLK = 0x0203;
|
||||
const WM_RBUTTONDOWN = 0x0204;
|
||||
const WM_RBUTTONUP = 0x0205;
|
||||
const WM_RBUTTONDBLCLK = 0x0206;
|
||||
const WM_MBUTTONDOWN = 0x0207;
|
||||
const WM_MBUTTONUP = 0x0208;
|
||||
const WM_MBUTTONDBLCLK = 0x0209;
|
||||
|
||||
PM_NOREMOVE :: 0x0000;
|
||||
PM_REMOVE :: 0x0001;
|
||||
PM_NOYIELD :: 0x0002;
|
||||
const PM_NOREMOVE = 0x0000;
|
||||
const PM_REMOVE = 0x0001;
|
||||
const PM_NOYIELD = 0x0002;
|
||||
|
||||
COLOR_BACKGROUND :: Hbrush(int(1));
|
||||
BLACK_BRUSH :: 4;
|
||||
const COLOR_BACKGROUND = Hbrush(int(1));
|
||||
const BLACK_BRUSH = 4;
|
||||
|
||||
SM_CXSCREEN :: 0;
|
||||
SM_CYSCREEN :: 1;
|
||||
const SM_CXSCREEN = 0;
|
||||
const SM_CYSCREEN = 1;
|
||||
|
||||
SW_SHOW :: 5;
|
||||
const SW_SHOW = 5;
|
||||
|
||||
|
||||
Point :: struct #ordered {
|
||||
const Point = struct #ordered {
|
||||
x, y: i32,
|
||||
}
|
||||
|
||||
WndClassExA :: struct #ordered {
|
||||
const WndClassExA = struct #ordered {
|
||||
size, style: u32,
|
||||
wnd_proc: WndProc,
|
||||
cls_extra, wnd_extra: i32,
|
||||
@@ -102,7 +102,7 @@ WndClassExA :: struct #ordered {
|
||||
sm: Hicon,
|
||||
}
|
||||
|
||||
Msg :: struct #ordered {
|
||||
const Msg = struct #ordered {
|
||||
hwnd: Hwnd,
|
||||
message: u32,
|
||||
wparam: Wparam,
|
||||
@@ -111,24 +111,24 @@ Msg :: struct #ordered {
|
||||
pt: Point,
|
||||
}
|
||||
|
||||
Rect :: struct #ordered {
|
||||
const Rect = struct #ordered {
|
||||
left: i32,
|
||||
top: i32,
|
||||
right: i32,
|
||||
bottom: i32,
|
||||
}
|
||||
|
||||
Filetime :: struct #ordered {
|
||||
const Filetime = struct #ordered {
|
||||
lo, hi: u32,
|
||||
}
|
||||
|
||||
Systemtime :: struct #ordered {
|
||||
const Systemtime = struct #ordered {
|
||||
year, month: u16,
|
||||
day_of_week, day: u16,
|
||||
hour, minute, second, millisecond: u16,
|
||||
}
|
||||
|
||||
ByHandleFileInformation :: struct #ordered {
|
||||
const ByHandleFileInformation = struct #ordered {
|
||||
file_attributes: u32,
|
||||
creation_time,
|
||||
last_access_time,
|
||||
@@ -141,7 +141,7 @@ ByHandleFileInformation :: struct #ordered {
|
||||
file_index_low: u32,
|
||||
}
|
||||
|
||||
FileAttributeData :: struct #ordered {
|
||||
const FileAttributeData = struct #ordered {
|
||||
file_attributes: u32,
|
||||
creation_time,
|
||||
last_access_time,
|
||||
@@ -150,7 +150,7 @@ FileAttributeData :: struct #ordered {
|
||||
file_size_low: u32,
|
||||
}
|
||||
|
||||
FindData :: struct #ordered {
|
||||
const FindData = struct #ordered {
|
||||
file_attributes : u32,
|
||||
creation_time : Filetime,
|
||||
last_access_time : Filetime,
|
||||
@@ -164,224 +164,224 @@ FindData :: struct #ordered {
|
||||
}
|
||||
|
||||
|
||||
GET_FILEEX_INFO_LEVELS :: i32;
|
||||
const GET_FILEEX_INFO_LEVELS = i32;
|
||||
|
||||
GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0;
|
||||
GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1;
|
||||
const GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS = 0;
|
||||
const GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS = 1;
|
||||
|
||||
get_last_error :: proc() -> i32 #foreign kernel32 "GetLastError";
|
||||
exit_process :: proc(exit_code: u32) #foreign kernel32 "ExitProcess";
|
||||
get_desktop_window :: proc() -> Hwnd #foreign user32 "GetDesktopWindow";
|
||||
show_cursor :: proc(show : Bool) #foreign user32 "ShowCursor";
|
||||
get_cursor_pos :: proc(p: ^Point) -> i32 #foreign user32 "GetCursorPos";
|
||||
screen_to_client :: proc(h: Hwnd, p: ^Point) -> i32 #foreign user32 "ScreenToClient";
|
||||
get_module_handle_a :: proc(module_name: ^u8) -> Hinstance #foreign kernel32 "GetModuleHandleA";
|
||||
get_stock_object :: proc(fn_object: i32) -> Hgdiobj #foreign gdi32 "GetStockObject";
|
||||
post_quit_message :: proc(exit_code: i32) #foreign user32 "PostQuitMessage";
|
||||
set_window_text_a :: proc(hwnd: Hwnd, c_string: ^u8) -> Bool #foreign user32 "SetWindowTextA";
|
||||
const get_last_error = proc() -> i32 #foreign kernel32 "GetLastError";
|
||||
const exit_process = proc(exit_code: u32) #foreign kernel32 "ExitProcess";
|
||||
const get_desktop_window = proc() -> Hwnd #foreign user32 "GetDesktopWindow";
|
||||
const show_cursor = proc(show : Bool) #foreign user32 "ShowCursor";
|
||||
const get_cursor_pos = proc(p: ^Point) -> i32 #foreign user32 "GetCursorPos";
|
||||
const screen_to_client = proc(h: Hwnd, p: ^Point) -> i32 #foreign user32 "ScreenToClient";
|
||||
const get_module_handle_a = proc(module_name: ^u8) -> Hinstance #foreign kernel32 "GetModuleHandleA";
|
||||
const get_stock_object = proc(fn_object: i32) -> Hgdiobj #foreign gdi32 "GetStockObject";
|
||||
const post_quit_message = proc(exit_code: i32) #foreign user32 "PostQuitMessage";
|
||||
const set_window_text_a = proc(hwnd: Hwnd, c_string: ^u8) -> Bool #foreign user32 "SetWindowTextA";
|
||||
|
||||
query_performance_frequency :: proc(result: ^i64) -> i32 #foreign kernel32 "QueryPerformanceFrequency";
|
||||
query_performance_counter :: proc(result: ^i64) -> i32 #foreign kernel32 "QueryPerformanceCounter";
|
||||
const query_performance_frequency = proc(result: ^i64) -> i32 #foreign kernel32 "QueryPerformanceFrequency";
|
||||
const query_performance_counter = proc(result: ^i64) -> i32 #foreign kernel32 "QueryPerformanceCounter";
|
||||
|
||||
sleep :: proc(ms: i32) -> i32 #foreign kernel32 "Sleep";
|
||||
const sleep = proc(ms: i32) -> i32 #foreign kernel32 "Sleep";
|
||||
|
||||
output_debug_string_a :: proc(c_str: ^u8) #foreign kernel32 "OutputDebugStringA";
|
||||
const output_debug_string_a = proc(c_str: ^u8) #foreign kernel32 "OutputDebugStringA";
|
||||
|
||||
|
||||
register_class_ex_a :: proc(wc: ^WndClassExA) -> i16 #foreign user32 "RegisterClassExA";
|
||||
create_window_ex_a :: proc(ex_style: u32,
|
||||
const register_class_ex_a = proc(wc: ^WndClassExA) -> i16 #foreign user32 "RegisterClassExA";
|
||||
const create_window_ex_a = 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 user32 "CreateWindowExA";
|
||||
|
||||
show_window :: proc(hwnd: Hwnd, cmd_show: i32) -> Bool #foreign user32 "ShowWindow";
|
||||
translate_message :: proc(msg: ^Msg) -> Bool #foreign user32 "TranslateMessage";
|
||||
dispatch_message_a :: proc(msg: ^Msg) -> Lresult #foreign user32 "DispatchMessageA";
|
||||
update_window :: proc(hwnd: Hwnd) -> Bool #foreign user32 "UpdateWindow";
|
||||
get_message_a :: proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool #foreign user32 "GetMessageA";
|
||||
peek_message_a :: proc(msg: ^Msg, hwnd: Hwnd,
|
||||
const show_window = proc(hwnd: Hwnd, cmd_show: i32) -> Bool #foreign user32 "ShowWindow";
|
||||
const translate_message = proc(msg: ^Msg) -> Bool #foreign user32 "TranslateMessage";
|
||||
const dispatch_message_a = proc(msg: ^Msg) -> Lresult #foreign user32 "DispatchMessageA";
|
||||
const update_window = proc(hwnd: Hwnd) -> Bool #foreign user32 "UpdateWindow";
|
||||
const get_message_a = proc(msg: ^Msg, hwnd: Hwnd, msg_filter_min, msg_filter_max : u32) -> Bool #foreign user32 "GetMessageA";
|
||||
const peek_message_a = proc(msg: ^Msg, hwnd: Hwnd,
|
||||
msg_filter_min, msg_filter_max, remove_msg: u32) -> Bool #foreign user32 "PeekMessageA";
|
||||
|
||||
post_message :: proc(hwnd: Hwnd, msg, wparam, lparam : u32) -> Bool #foreign user32 "PostMessageA";
|
||||
const post_message = proc(hwnd: Hwnd, msg, wparam, lparam : u32) -> Bool #foreign user32 "PostMessageA";
|
||||
|
||||
def_window_proc_a :: proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult #foreign user32 "DefWindowProcA";
|
||||
const def_window_proc_a = proc(hwnd: Hwnd, msg: u32, wparam: Wparam, lparam: Lparam) -> Lresult #foreign user32 "DefWindowProcA";
|
||||
|
||||
adjust_window_rect :: proc(rect: ^Rect, style: u32, menu: Bool) -> Bool #foreign user32 "AdjustWindowRect";
|
||||
get_active_window :: proc() -> Hwnd #foreign user32 "GetActiveWindow";
|
||||
const adjust_window_rect = proc(rect: ^Rect, style: u32, menu: Bool) -> Bool #foreign user32 "AdjustWindowRect";
|
||||
const get_active_window = proc() -> Hwnd #foreign user32 "GetActiveWindow";
|
||||
|
||||
destroy_window :: proc(wnd: Hwnd) -> Bool #foreign user32 "DestroyWindow";
|
||||
describe_pixel_format :: proc(dc: Hdc, pixel_format: i32, bytes : u32, pfd: ^PixelFormatDescriptor) -> i32 #foreign user32 "DescribePixelFormat";
|
||||
const destroy_window = proc(wnd: Hwnd) -> Bool #foreign user32 "DestroyWindow";
|
||||
const describe_pixel_format = proc(dc: Hdc, pixel_format: i32, bytes : u32, pfd: ^PixelFormatDescriptor) -> i32 #foreign user32 "DescribePixelFormat";
|
||||
|
||||
|
||||
get_query_performance_frequency :: proc() -> i64 {
|
||||
r: i64;
|
||||
const get_query_performance_frequency = proc() -> i64 {
|
||||
var r: i64;
|
||||
query_performance_frequency(&r);
|
||||
return r;
|
||||
}
|
||||
|
||||
get_command_line_a :: proc() -> ^u8 #foreign kernel32 "GetCommandLineA";
|
||||
get_command_line_w :: proc() -> ^u16 #foreign kernel32 "GetCommandLineW";
|
||||
get_system_metrics :: proc(index: i32) -> i32 #foreign kernel32 "GetSystemMetrics";
|
||||
get_current_thread_id :: proc() -> u32 #foreign kernel32 "GetCurrentThreadId";
|
||||
command_line_to_argv_w :: proc(cmd_list: ^u16, num_args: ^i32) -> ^^u16 #foreign shell32 "CommandLineToArgvW";
|
||||
const get_command_line_a = proc() -> ^u8 #foreign kernel32 "GetCommandLineA";
|
||||
const get_command_line_w = proc() -> ^u16 #foreign kernel32 "GetCommandLineW";
|
||||
const get_system_metrics = proc(index: i32) -> i32 #foreign kernel32 "GetSystemMetrics";
|
||||
const get_current_thread_id = proc() -> u32 #foreign kernel32 "GetCurrentThreadId";
|
||||
const command_line_to_argv_w = proc(cmd_list: ^u16, num_args: ^i32) -> ^^u16 #foreign shell32 "CommandLineToArgvW";
|
||||
|
||||
time_get_time :: proc() -> u32 #foreign winmm "timeGetTime";
|
||||
get_system_time_as_file_time :: proc(system_time_as_file_time: ^Filetime) #foreign kernel32 "GetSystemTimeAsFileTime";
|
||||
file_time_to_local_file_time :: proc(file_time: ^Filetime, local_file_time: ^Filetime) -> Bool #foreign kernel32 "FileTimeToLocalFileTime";
|
||||
file_time_to_system_time :: proc(file_time: ^Filetime, system_time: ^Systemtime) -> Bool #foreign kernel32 "FileTimeToSystemTime";
|
||||
system_time_to_file_time :: proc(system_time: ^Systemtime, file_time: ^Filetime) -> Bool #foreign kernel32 "SystemTimeToFileTime";
|
||||
const time_get_time = proc() -> u32 #foreign winmm "timeGetTime";
|
||||
const get_system_time_as_file_time = proc(system_time_as_file_time: ^Filetime) #foreign kernel32 "GetSystemTimeAsFileTime";
|
||||
const file_time_to_local_file_time = proc(file_time: ^Filetime, local_file_time: ^Filetime) -> Bool #foreign kernel32 "FileTimeToLocalFileTime";
|
||||
const file_time_to_system_time = proc(file_time: ^Filetime, system_time: ^Systemtime) -> Bool #foreign kernel32 "FileTimeToSystemTime";
|
||||
const system_time_to_file_time = proc(system_time: ^Systemtime, file_time: ^Filetime) -> Bool #foreign kernel32 "SystemTimeToFileTime";
|
||||
|
||||
// File Stuff
|
||||
|
||||
close_handle :: proc(h: Handle) -> i32 #foreign kernel32 "CloseHandle";
|
||||
get_std_handle :: proc(h: i32) -> Handle #foreign kernel32 "GetStdHandle";
|
||||
create_file_a :: proc(filename: ^u8, desired_access, share_mode: u32,
|
||||
const close_handle = proc(h: Handle) -> i32 #foreign kernel32 "CloseHandle";
|
||||
const get_std_handle = proc(h: i32) -> Handle #foreign kernel32 "GetStdHandle";
|
||||
const create_file_a = proc(filename: ^u8, desired_access, share_mode: u32,
|
||||
security: rawptr,
|
||||
creation, flags_and_attribs: u32, template_file: Handle) -> Handle #foreign kernel32 "CreateFileA";
|
||||
read_file :: proc(h: Handle, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> Bool #foreign kernel32 "ReadFile";
|
||||
write_file :: proc(h: Handle, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> Bool #foreign kernel32 "WriteFile";
|
||||
const read_file = proc(h: Handle, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> Bool #foreign kernel32 "ReadFile";
|
||||
const write_file = proc(h: Handle, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> Bool #foreign kernel32 "WriteFile";
|
||||
|
||||
get_file_size_ex :: proc(file_handle: Handle, file_size: ^i64) -> Bool #foreign kernel32 "GetFileSizeEx";
|
||||
get_file_attributes_a :: proc(filename: ^u8) -> u32 #foreign kernel32 "GetFileAttributesA";
|
||||
get_file_attributes_ex_a :: proc(filename: ^u8, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool #foreign kernel32 "GetFileAttributesExA";
|
||||
get_file_information_by_handle :: proc(file_handle: Handle, file_info: ^ByHandleFileInformation) -> Bool #foreign kernel32 "GetFileInformationByHandle";
|
||||
const get_file_size_ex = proc(file_handle: Handle, file_size: ^i64) -> Bool #foreign kernel32 "GetFileSizeEx";
|
||||
const get_file_attributes_a = proc(filename: ^u8) -> u32 #foreign kernel32 "GetFileAttributesA";
|
||||
const get_file_attributes_ex_a = proc(filename: ^u8, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> Bool #foreign kernel32 "GetFileAttributesExA";
|
||||
const get_file_information_by_handle = proc(file_handle: Handle, file_info: ^ByHandleFileInformation) -> Bool #foreign kernel32 "GetFileInformationByHandle";
|
||||
|
||||
get_file_type :: proc(file_handle: Handle) -> u32 #foreign kernel32 "GetFileType";
|
||||
set_file_pointer :: proc(file_handle: Handle, distance_to_move: i32, distance_to_move_high: ^i32, move_method: u32) -> u32 #foreign kernel32 "SetFilePointer";
|
||||
const get_file_type = proc(file_handle: Handle) -> u32 #foreign kernel32 "GetFileType";
|
||||
const set_file_pointer = proc(file_handle: Handle, distance_to_move: i32, distance_to_move_high: ^i32, move_method: u32) -> u32 #foreign kernel32 "SetFilePointer";
|
||||
|
||||
set_handle_information :: proc(obj: Handle, mask, flags: u32) -> Bool #foreign kernel32 "SetHandleInformation";
|
||||
const set_handle_information = proc(obj: Handle, mask, flags: u32) -> Bool #foreign kernel32 "SetHandleInformation";
|
||||
|
||||
find_first_file_a :: proc(file_name : ^u8, data : ^FindData) -> Handle #foreign kernel32 "FindFirstFileA";
|
||||
find_next_file_a :: proc(file : Handle, data : ^FindData) -> Bool #foreign kernel32 "FindNextFileA";
|
||||
find_close :: proc(file : Handle) -> Bool #foreign kernel32 "FindClose";
|
||||
const find_first_file_a = proc(file_name : ^u8, data : ^FindData) -> Handle #foreign kernel32 "FindFirstFileA";
|
||||
const find_next_file_a = proc(file : Handle, data : ^FindData) -> Bool #foreign kernel32 "FindNextFileA";
|
||||
const find_close = proc(file : Handle) -> Bool #foreign kernel32 "FindClose";
|
||||
|
||||
MAX_PATH :: 0x00000104;
|
||||
const MAX_PATH = 0x00000104;
|
||||
|
||||
HANDLE_FLAG_INHERIT :: 1;
|
||||
HANDLE_FLAG_PROTECT_FROM_CLOSE :: 2;
|
||||
const HANDLE_FLAG_INHERIT = 1;
|
||||
const HANDLE_FLAG_PROTECT_FROM_CLOSE = 2;
|
||||
|
||||
|
||||
FILE_BEGIN :: 0;
|
||||
FILE_CURRENT :: 1;
|
||||
FILE_END :: 2;
|
||||
const FILE_BEGIN = 0;
|
||||
const FILE_CURRENT = 1;
|
||||
const FILE_END = 2;
|
||||
|
||||
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;
|
||||
const FILE_SHARE_READ = 0x00000001;
|
||||
const FILE_SHARE_WRITE = 0x00000002;
|
||||
const FILE_SHARE_DELETE = 0x00000004;
|
||||
const FILE_GENERIC_ALL = 0x10000000;
|
||||
const FILE_GENERIC_EXECUTE = 0x20000000;
|
||||
const FILE_GENERIC_WRITE = 0x40000000;
|
||||
const FILE_GENERIC_READ = 0x80000000;
|
||||
|
||||
FILE_APPEND_DATA :: 0x0004;
|
||||
const FILE_APPEND_DATA = 0x0004;
|
||||
|
||||
STD_INPUT_HANDLE :: -10;
|
||||
STD_OUTPUT_HANDLE :: -11;
|
||||
STD_ERROR_HANDLE :: -12;
|
||||
const STD_INPUT_HANDLE = -10;
|
||||
const STD_OUTPUT_HANDLE = -11;
|
||||
const STD_ERROR_HANDLE = -12;
|
||||
|
||||
CREATE_NEW :: 1;
|
||||
CREATE_ALWAYS :: 2;
|
||||
OPEN_EXISTING :: 3;
|
||||
OPEN_ALWAYS :: 4;
|
||||
TRUNCATE_EXISTING :: 5;
|
||||
const CREATE_NEW = 1;
|
||||
const CREATE_ALWAYS = 2;
|
||||
const OPEN_EXISTING = 3;
|
||||
const OPEN_ALWAYS = 4;
|
||||
const TRUNCATE_EXISTING = 5;
|
||||
|
||||
INVALID_FILE_ATTRIBUTES :: -1;
|
||||
const INVALID_FILE_ATTRIBUTES = -1;
|
||||
|
||||
FILE_ATTRIBUTE_READONLY :: 0x00000001;
|
||||
FILE_ATTRIBUTE_HIDDEN :: 0x00000002;
|
||||
FILE_ATTRIBUTE_SYSTEM :: 0x00000004;
|
||||
FILE_ATTRIBUTE_DIRECTORY :: 0x00000010;
|
||||
FILE_ATTRIBUTE_ARCHIVE :: 0x00000020;
|
||||
FILE_ATTRIBUTE_DEVICE :: 0x00000040;
|
||||
FILE_ATTRIBUTE_NORMAL :: 0x00000080;
|
||||
FILE_ATTRIBUTE_TEMPORARY :: 0x00000100;
|
||||
FILE_ATTRIBUTE_SPARSE_FILE :: 0x00000200;
|
||||
FILE_ATTRIBUTE_REPARSE_Point :: 0x00000400;
|
||||
FILE_ATTRIBUTE_COMPRESSED :: 0x00000800;
|
||||
FILE_ATTRIBUTE_OFFLINE :: 0x00001000;
|
||||
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED :: 0x00002000;
|
||||
FILE_ATTRIBUTE_ENCRYPTED :: 0x00004000;
|
||||
const FILE_ATTRIBUTE_READONLY = 0x00000001;
|
||||
const FILE_ATTRIBUTE_HIDDEN = 0x00000002;
|
||||
const FILE_ATTRIBUTE_SYSTEM = 0x00000004;
|
||||
const FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
|
||||
const FILE_ATTRIBUTE_ARCHIVE = 0x00000020;
|
||||
const FILE_ATTRIBUTE_DEVICE = 0x00000040;
|
||||
const FILE_ATTRIBUTE_NORMAL = 0x00000080;
|
||||
const FILE_ATTRIBUTE_TEMPORARY = 0x00000100;
|
||||
const FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200;
|
||||
const FILE_ATTRIBUTE_REPARSE_Point = 0x00000400;
|
||||
const FILE_ATTRIBUTE_COMPRESSED = 0x00000800;
|
||||
const FILE_ATTRIBUTE_OFFLINE = 0x00001000;
|
||||
const FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000;
|
||||
const FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
|
||||
|
||||
FILE_TYPE_DISK :: 0x0001;
|
||||
FILE_TYPE_CHAR :: 0x0002;
|
||||
FILE_TYPE_PIPE :: 0x0003;
|
||||
const FILE_TYPE_DISK = 0x0001;
|
||||
const FILE_TYPE_CHAR = 0x0002;
|
||||
const FILE_TYPE_PIPE = 0x0003;
|
||||
|
||||
INVALID_SET_FILE_POINTER :: ~u32(0);
|
||||
const INVALID_SET_FILE_POINTER = ~u32(0);
|
||||
|
||||
|
||||
|
||||
|
||||
heap_alloc :: proc (h: Handle, flags: u32, bytes: int) -> rawptr #foreign kernel32 "HeapAlloc";
|
||||
heap_realloc :: proc (h: Handle, flags: u32, memory: rawptr, bytes: int) -> rawptr #foreign kernel32 "HeapReAlloc";
|
||||
heap_free :: proc (h: Handle, flags: u32, memory: rawptr) -> Bool #foreign kernel32 "HeapFree";
|
||||
get_process_heap :: proc () -> Handle #foreign kernel32 "GetProcessHeap";
|
||||
const heap_alloc = proc (h: Handle, flags: u32, bytes: int) -> rawptr #foreign kernel32 "HeapAlloc";
|
||||
const heap_realloc = proc (h: Handle, flags: u32, memory: rawptr, bytes: int) -> rawptr #foreign kernel32 "HeapReAlloc";
|
||||
const heap_free = proc (h: Handle, flags: u32, memory: rawptr) -> Bool #foreign kernel32 "HeapFree";
|
||||
const get_process_heap = proc () -> Handle #foreign kernel32 "GetProcessHeap";
|
||||
|
||||
|
||||
HEAP_ZERO_MEMORY :: 0x00000008;
|
||||
const HEAP_ZERO_MEMORY = 0x00000008;
|
||||
|
||||
// Synchronization
|
||||
|
||||
Security_Attributes :: struct #ordered {
|
||||
const Security_Attributes = struct #ordered {
|
||||
length: u32,
|
||||
security_descriptor: rawptr,
|
||||
inherit_handle: Bool,
|
||||
}
|
||||
|
||||
INFINITE :: 0xffffffff;
|
||||
const INFINITE = 0xffffffff;
|
||||
|
||||
create_semaphore_a :: proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: ^u8) -> Handle #foreign kernel32 "CreateSemaphoreA";
|
||||
release_semaphore :: proc(semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool #foreign kernel32 "ReleaseSemaphore";
|
||||
wait_for_single_object :: proc(handle: Handle, milliseconds: u32) -> u32 #foreign kernel32 "WaitForSingleObject";
|
||||
const create_semaphore_a = proc(attributes: ^Security_Attributes, initial_count, maximum_count: i32, name: ^u8) -> Handle #foreign kernel32 "CreateSemaphoreA";
|
||||
const release_semaphore = proc(semaphore: Handle, release_count: i32, previous_count: ^i32) -> Bool #foreign kernel32 "ReleaseSemaphore";
|
||||
const wait_for_single_object = proc(handle: Handle, milliseconds: u32) -> u32 #foreign kernel32 "WaitForSingleObject";
|
||||
|
||||
|
||||
interlocked_compare_exchange :: proc(dst: ^i32, exchange, comparand: i32) -> i32 #foreign kernel32 "InterlockedCompareExchange";
|
||||
interlocked_exchange :: proc(dst: ^i32, desired: i32) -> i32 #foreign kernel32 "InterlockedExchange";
|
||||
interlocked_exchange_add :: proc(dst: ^i32, desired: i32) -> i32 #foreign kernel32 "InterlockedExchangeAdd";
|
||||
interlocked_and :: proc(dst: ^i32, desired: i32) -> i32 #foreign kernel32 "InterlockedAnd";
|
||||
interlocked_or :: proc(dst: ^i32, desired: i32) -> i32 #foreign kernel32 "InterlockedOr";
|
||||
const interlocked_compare_exchange = proc(dst: ^i32, exchange, comparand: i32) -> i32 #foreign kernel32 "InterlockedCompareExchange";
|
||||
const interlocked_exchange = proc(dst: ^i32, desired: i32) -> i32 #foreign kernel32 "InterlockedExchange";
|
||||
const interlocked_exchange_add = proc(dst: ^i32, desired: i32) -> i32 #foreign kernel32 "InterlockedExchangeAdd";
|
||||
const interlocked_and = proc(dst: ^i32, desired: i32) -> i32 #foreign kernel32 "InterlockedAnd";
|
||||
const interlocked_or = proc(dst: ^i32, desired: i32) -> i32 #foreign kernel32 "InterlockedOr";
|
||||
|
||||
interlocked_compare_exchange64 :: proc(dst: ^i64, exchange, comparand: i64) -> i64 #foreign kernel32 "InterlockedCompareExchange64";
|
||||
interlocked_exchange64 :: proc(dst: ^i64, desired: i64) -> i64 #foreign kernel32 "InterlockedExchange64";
|
||||
interlocked_exchange_add64 :: proc(dst: ^i64, desired: i64) -> i64 #foreign kernel32 "InterlockedExchangeAdd64";
|
||||
interlocked_and64 :: proc(dst: ^i64, desired: i64) -> i64 #foreign kernel32 "InterlockedAnd64";
|
||||
interlocked_or64 :: proc(dst: ^i64, desired: i64) -> i64 #foreign kernel32 "InterlockedOr64";
|
||||
const interlocked_compare_exchange64 = proc(dst: ^i64, exchange, comparand: i64) -> i64 #foreign kernel32 "InterlockedCompareExchange64";
|
||||
const interlocked_exchange64 = proc(dst: ^i64, desired: i64) -> i64 #foreign kernel32 "InterlockedExchange64";
|
||||
const interlocked_exchange_add64 = proc(dst: ^i64, desired: i64) -> i64 #foreign kernel32 "InterlockedExchangeAdd64";
|
||||
const interlocked_and64 = proc(dst: ^i64, desired: i64) -> i64 #foreign kernel32 "InterlockedAnd64";
|
||||
const interlocked_or64 = proc(dst: ^i64, desired: i64) -> i64 #foreign kernel32 "InterlockedOr64";
|
||||
|
||||
mm_pause :: proc() #foreign kernel32 "_mm_pause";
|
||||
read_write_barrier :: proc() #foreign kernel32 "ReadWriteBarrier";
|
||||
write_barrier :: proc() #foreign kernel32 "WriteBarrier";
|
||||
read_barrier :: proc() #foreign kernel32 "ReadBarrier";
|
||||
const mm_pause = proc() #foreign kernel32 "_mm_pause";
|
||||
const read_write_barrier = proc() #foreign kernel32 "ReadWriteBarrier";
|
||||
const write_barrier = proc() #foreign kernel32 "WriteBarrier";
|
||||
const read_barrier = proc() #foreign kernel32 "ReadBarrier";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Hmonitor :: Handle;
|
||||
const Hmonitor = Handle;
|
||||
|
||||
GWL_STYLE :: -16;
|
||||
const GWL_STYLE = -16;
|
||||
|
||||
Hwnd_TOP :: Hwnd(uint(0));
|
||||
const Hwnd_TOP = Hwnd(uint(0));
|
||||
|
||||
MONITOR_DEFAULTTONULL :: 0x00000000;
|
||||
MONITOR_DEFAULTTOPRIMARY :: 0x00000001;
|
||||
MONITOR_DEFAULTTONEAREST :: 0x00000002;
|
||||
const MONITOR_DEFAULTTONULL = 0x00000000;
|
||||
const MONITOR_DEFAULTTOPRIMARY = 0x00000001;
|
||||
const MONITOR_DEFAULTTONEAREST = 0x00000002;
|
||||
|
||||
SWP_FRAMECHANGED :: 0x0020;
|
||||
SWP_NOOWNERZORDER :: 0x0200;
|
||||
SWP_NOZORDER :: 0x0004;
|
||||
SWP_NOSIZE :: 0x0001;
|
||||
SWP_NOMOVE :: 0x0002;
|
||||
const SWP_FRAMECHANGED = 0x0020;
|
||||
const SWP_NOOWNERZORDER = 0x0200;
|
||||
const SWP_NOZORDER = 0x0004;
|
||||
const SWP_NOSIZE = 0x0001;
|
||||
const SWP_NOMOVE = 0x0002;
|
||||
|
||||
|
||||
MonitorInfo :: struct #ordered {
|
||||
const MonitorInfo = struct #ordered {
|
||||
size: u32,
|
||||
monitor: Rect,
|
||||
work: Rect,
|
||||
flags: u32,
|
||||
}
|
||||
|
||||
WindowPlacement :: struct #ordered {
|
||||
const WindowPlacement = struct #ordered {
|
||||
length: u32,
|
||||
flags: u32,
|
||||
show_cmd: u32,
|
||||
@@ -390,24 +390,24 @@ WindowPlacement :: struct #ordered {
|
||||
normal_pos: Rect,
|
||||
}
|
||||
|
||||
get_monitor_info_a :: proc(monitor: Hmonitor, mi: ^MonitorInfo) -> Bool #foreign user32 "GetMonitorInfoA";
|
||||
monitor_from_window :: proc(wnd: Hwnd, flags : u32) -> Hmonitor #foreign user32 "MonitorFromWindow";
|
||||
const get_monitor_info_a = proc(monitor: Hmonitor, mi: ^MonitorInfo) -> Bool #foreign user32 "GetMonitorInfoA";
|
||||
const monitor_from_window = proc(wnd: Hwnd, flags : u32) -> Hmonitor #foreign user32 "MonitorFromWindow";
|
||||
|
||||
set_window_pos :: proc(wnd: Hwnd, wndInsertAfter: Hwnd, x, y, width, height: i32, flags: u32) #foreign user32 "SetWindowPos";
|
||||
const set_window_pos = proc(wnd: Hwnd, wndInsertAfter: Hwnd, x, y, width, height: i32, flags: u32) #foreign user32 "SetWindowPos";
|
||||
|
||||
get_window_placement :: proc(wnd: Hwnd, wndpl: ^WindowPlacement) -> Bool #foreign user32 "GetWindowPlacement";
|
||||
set_window_placement :: proc(wnd: Hwnd, wndpl: ^WindowPlacement) -> Bool #foreign user32 "SetWindowPlacement";
|
||||
get_window_rect :: proc(wnd: Hwnd, rect: ^Rect) -> Bool #foreign user32 "GetWindowRect";
|
||||
const get_window_placement = proc(wnd: Hwnd, wndpl: ^WindowPlacement) -> Bool #foreign user32 "GetWindowPlacement";
|
||||
const set_window_placement = proc(wnd: Hwnd, wndpl: ^WindowPlacement) -> Bool #foreign user32 "SetWindowPlacement";
|
||||
const get_window_rect = proc(wnd: Hwnd, rect: ^Rect) -> Bool #foreign user32 "GetWindowRect";
|
||||
|
||||
get_window_long_ptr_a :: proc(wnd: Hwnd, index: i32) -> i64 #foreign user32 "GetWindowLongPtrA";
|
||||
set_window_long_ptr_a :: proc(wnd: Hwnd, index: i32, new: i64) -> i64 #foreign user32 "SetWindowLongPtrA";
|
||||
const get_window_long_ptr_a = proc(wnd: Hwnd, index: i32) -> i64 #foreign user32 "GetWindowLongPtrA";
|
||||
const set_window_long_ptr_a = proc(wnd: Hwnd, index: i32, new: i64) -> i64 #foreign user32 "SetWindowLongPtrA";
|
||||
|
||||
get_window_text :: proc(wnd: Hwnd, str: ^u8, maxCount: i32) -> i32 #foreign user32 "GetWindowText";
|
||||
const get_window_text = proc(wnd: Hwnd, str: ^u8, maxCount: i32) -> i32 #foreign user32 "GetWindowText";
|
||||
|
||||
HIWORD :: proc(wParam: Wparam) -> u16 { return u16((u32(wParam) >> 16) & 0xffff); }
|
||||
HIWORD :: proc(lParam: Lparam) -> u16 { return u16((u32(lParam) >> 16) & 0xffff); }
|
||||
LOWORD :: proc(wParam: Wparam) -> u16 { return u16(wParam); }
|
||||
LOWORD :: proc(lParam: Lparam) -> u16 { return u16(lParam); }
|
||||
const HIWORD = proc(wParam: Wparam) -> u16 { return u16((u32(wParam) >> 16) & 0xffff); }
|
||||
const HIWORD = proc(lParam: Lparam) -> u16 { return u16((u32(lParam) >> 16) & 0xffff); }
|
||||
const LOWORD = proc(wParam: Wparam) -> u16 { return u16(wParam); }
|
||||
const LOWORD = proc(lParam: Lparam) -> u16 { return u16(lParam); }
|
||||
|
||||
|
||||
|
||||
@@ -418,7 +418,7 @@ LOWORD :: proc(lParam: Lparam) -> u16 { return u16(lParam); }
|
||||
|
||||
|
||||
|
||||
BitmapInfoHeader :: struct #ordered {
|
||||
const BitmapInfoHeader = struct #ordered {
|
||||
size: u32,
|
||||
width, height: i32,
|
||||
planes, bit_count: i16,
|
||||
@@ -429,20 +429,20 @@ BitmapInfoHeader :: struct #ordered {
|
||||
clr_used: u32,
|
||||
clr_important: u32,
|
||||
}
|
||||
BitmapInfo :: struct #ordered {
|
||||
const BitmapInfo = struct #ordered {
|
||||
using header: BitmapInfoHeader,
|
||||
colors: [1]RgbQuad,
|
||||
}
|
||||
|
||||
|
||||
RgbQuad :: struct #ordered { blue, green, red, reserved: u8 }
|
||||
const RgbQuad = struct #ordered { blue, green, red, reserved: u8 }
|
||||
|
||||
BI_RGB :: 0;
|
||||
DIB_RGB_COLORS :: 0x00;
|
||||
SRCCOPY: u32 : 0x00cc0020;
|
||||
const BI_RGB = 0;
|
||||
const DIB_RGB_COLORS = 0x00;
|
||||
const SRCCOPY: u32 = 0x00cc0020;
|
||||
|
||||
|
||||
stretch_dibits :: proc (hdc: Hdc,
|
||||
const stretch_dibits = 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,
|
||||
@@ -451,37 +451,37 @@ stretch_dibits :: proc (hdc: Hdc,
|
||||
|
||||
|
||||
|
||||
load_library_a :: proc (c_str: ^u8) -> Hmodule #foreign kernel32 "LoadLibraryA";
|
||||
free_library :: proc (h: Hmodule) #foreign kernel32 "FreeLibrary";
|
||||
get_proc_address :: proc (h: Hmodule, c_str: ^u8) -> Proc #foreign kernel32 "GetProcAddress";
|
||||
const load_library_a = proc (c_str: ^u8) -> Hmodule #foreign kernel32 "LoadLibraryA";
|
||||
const free_library = proc (h: Hmodule) #foreign kernel32 "FreeLibrary";
|
||||
const get_proc_address = proc (h: Hmodule, c_str: ^u8) -> Proc #foreign kernel32 "GetProcAddress";
|
||||
|
||||
get_client_rect :: proc(hwnd: Hwnd, rect: ^Rect) -> Bool #foreign user32 "GetClientRect";
|
||||
const get_client_rect = proc(hwnd: Hwnd, rect: ^Rect) -> Bool #foreign user32 "GetClientRect";
|
||||
|
||||
// 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;
|
||||
const PFD_TYPE_RGBA = 0;
|
||||
const PFD_TYPE_COLORINDEX = 1;
|
||||
const PFD_MAIN_PLANE = 0;
|
||||
const PFD_OVERLAY_PLANE = 1;
|
||||
const PFD_UNDERLAY_PLANE = -1;
|
||||
const PFD_DOUBLEBUFFER = 1;
|
||||
const PFD_STEREO = 2;
|
||||
const PFD_DRAW_TO_WINDOW = 4;
|
||||
const PFD_DRAW_TO_BITMAP = 8;
|
||||
const PFD_SUPPORT_GDI = 16;
|
||||
const PFD_SUPPORT_OPENGL = 32;
|
||||
const PFD_GENERIC_FORMAT = 64;
|
||||
const PFD_NEED_PALETTE = 128;
|
||||
const PFD_NEED_SYSTEM_PALETTE = 0x00000100;
|
||||
const PFD_SWAP_EXCHANGE = 0x00000200;
|
||||
const PFD_SWAP_COPY = 0x00000400;
|
||||
const PFD_SWAP_LAYER_BUFFERS = 0x00000800;
|
||||
const PFD_GENERIC_ACCELERATED = 0x00001000;
|
||||
const PFD_DEPTH_DONTCARE = 0x20000000;
|
||||
const PFD_DOUBLEBUFFER_DONTCARE = 0x40000000;
|
||||
const PFD_STEREO_DONTCARE = 0x80000000;
|
||||
|
||||
|
||||
PixelFormatDescriptor :: struct #ordered {
|
||||
const PixelFormatDescriptor = struct #ordered {
|
||||
size,
|
||||
version,
|
||||
flags: u32,
|
||||
@@ -512,28 +512,28 @@ PixelFormatDescriptor :: struct #ordered {
|
||||
damage_mask: u32,
|
||||
}
|
||||
|
||||
get_dc :: proc(h: Hwnd) -> Hdc #foreign user32 "GetDC";
|
||||
set_pixel_format :: proc(hdc: Hdc, pixel_format: i32, pfd: ^PixelFormatDescriptor) -> Bool #foreign gdi32 "SetPixelFormat";
|
||||
choose_pixel_format :: proc(hdc: Hdc, pfd: ^PixelFormatDescriptor) -> i32 #foreign gdi32 "ChoosePixelFormat";
|
||||
swap_buffers :: proc(hdc: Hdc) -> Bool #foreign gdi32 "SwapBuffers";
|
||||
release_dc :: proc(wnd: Hwnd, hdc: Hdc) -> i32 #foreign user32 "ReleaseDC";
|
||||
const get_dc = proc(h: Hwnd) -> Hdc #foreign user32 "GetDC";
|
||||
const set_pixel_format = proc(hdc: Hdc, pixel_format: i32, pfd: ^PixelFormatDescriptor) -> Bool #foreign gdi32 "SetPixelFormat";
|
||||
const choose_pixel_format = proc(hdc: Hdc, pfd: ^PixelFormatDescriptor) -> i32 #foreign gdi32 "ChoosePixelFormat";
|
||||
const swap_buffers = proc(hdc: Hdc) -> Bool #foreign gdi32 "SwapBuffers";
|
||||
const release_dc = proc(wnd: Hwnd, hdc: Hdc) -> i32 #foreign user32 "ReleaseDC";
|
||||
|
||||
|
||||
Proc :: #type proc() #cc_c;
|
||||
const Proc = type proc() #cc_c;
|
||||
|
||||
MAPVK_VK_TO_CHAR :: 2;
|
||||
MAPVK_VK_TO_VSC :: 0;
|
||||
MAPVK_VSC_TO_VK :: 1;
|
||||
MAPVK_VSC_TO_VK_EX :: 3;
|
||||
const MAPVK_VK_TO_CHAR = 2;
|
||||
const MAPVK_VK_TO_VSC = 0;
|
||||
const MAPVK_VSC_TO_VK = 1;
|
||||
const MAPVK_VSC_TO_VK_EX = 3;
|
||||
|
||||
map_virtual_key :: proc(scancode : u32, map_type : u32) -> u32 #foreign user32 "MapVirtualKeyA";
|
||||
const map_virtual_key = proc(scancode : u32, map_type : u32) -> u32 #foreign user32 "MapVirtualKeyA";
|
||||
|
||||
get_key_state :: proc(v_key: i32) -> i16 #foreign user32 "GetKeyState";
|
||||
get_async_key_state :: proc(v_key: i32) -> i16 #foreign user32 "GetAsyncKeyState";
|
||||
const get_key_state = proc(v_key: i32) -> i16 #foreign user32 "GetKeyState";
|
||||
const get_async_key_state = proc(v_key: i32) -> i16 #foreign user32 "GetAsyncKeyState";
|
||||
|
||||
is_key_down :: proc(key: KeyCode) -> bool #inline { return get_async_key_state(i32(key)) < 0; }
|
||||
const is_key_down = proc(key: KeyCode) -> bool #inline { return get_async_key_state(i32(key)) < 0; }
|
||||
|
||||
KeyCode :: enum i32 {
|
||||
const KeyCode = enum i32 {
|
||||
Lbutton = 0x01,
|
||||
Rbutton = 0x02,
|
||||
Cancel = 0x03,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
is_signed :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_signed = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
match i in type_info_base(info) {
|
||||
case TypeInfo.Integer: return i.signed;
|
||||
@@ -6,93 +6,93 @@ is_signed :: proc(info: ^TypeInfo) -> bool {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
is_integer :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_integer = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Integer);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Integer);
|
||||
return ok;
|
||||
}
|
||||
is_float :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_float = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Float);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Float);
|
||||
return ok;
|
||||
}
|
||||
is_complex :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_complex = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Complex);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Complex);
|
||||
return ok;
|
||||
}
|
||||
is_any :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_any = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Any);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Any);
|
||||
return ok;
|
||||
}
|
||||
is_string :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_string = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.String);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.String);
|
||||
return ok;
|
||||
}
|
||||
is_boolean :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_boolean = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Boolean);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Boolean);
|
||||
return ok;
|
||||
}
|
||||
is_pointer :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_pointer = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Pointer);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Pointer);
|
||||
return ok;
|
||||
}
|
||||
is_procedure :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_procedure = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Procedure);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Procedure);
|
||||
return ok;
|
||||
}
|
||||
is_array :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_array = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Array);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Array);
|
||||
return ok;
|
||||
}
|
||||
is_dynamic_array :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_dynamic_array = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.DynamicArray);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.DynamicArray);
|
||||
return ok;
|
||||
}
|
||||
is_dynamic_map :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_dynamic_map = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Map);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Map);
|
||||
return ok;
|
||||
}
|
||||
is_slice :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_slice = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Slice);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Slice);
|
||||
return ok;
|
||||
}
|
||||
is_vector :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_vector = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Vector);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Vector);
|
||||
return ok;
|
||||
}
|
||||
is_tuple :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_tuple = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Tuple);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Tuple);
|
||||
return ok;
|
||||
}
|
||||
is_struct :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_struct = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Struct);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Struct);
|
||||
return ok;
|
||||
}
|
||||
is_union :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_union = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Union);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Union);
|
||||
return ok;
|
||||
}
|
||||
is_raw_union :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_raw_union = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.RawUnion);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.RawUnion);
|
||||
return ok;
|
||||
}
|
||||
is_enum :: proc(info: ^TypeInfo) -> bool {
|
||||
const is_enum = proc(info: ^TypeInfo) -> bool {
|
||||
if info == nil { return false; }
|
||||
_, ok := type_info_base(info).(^TypeInfo.Enum);
|
||||
var _, ok = type_info_base(info).(^TypeInfo.Enum);
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
REPLACEMENT_CHAR :: '\uFFFD';
|
||||
MAX_RUNE :: '\U0010FFFF';
|
||||
const REPLACEMENT_CHAR = '\uFFFD';
|
||||
const MAX_RUNE = '\U0010FFFF';
|
||||
|
||||
_surr1 :: 0xd800;
|
||||
_surr2 :: 0xdc00;
|
||||
_surr3 :: 0xe000;
|
||||
_surr_self :: 0x10000;
|
||||
const _surr1 = 0xd800;
|
||||
const _surr2 = 0xdc00;
|
||||
const _surr3 = 0xe000;
|
||||
const _surr_self = 0x10000;
|
||||
|
||||
|
||||
is_surrogate :: proc(r: rune) -> bool {
|
||||
const is_surrogate = proc(r: rune) -> bool {
|
||||
return _surr1 <= r && r < _surr3;
|
||||
}
|
||||
|
||||
decode_surrogate_pair :: proc(r1, r2: rune) -> rune {
|
||||
const decode_surrogate_pair = proc(r1, r2: rune) -> rune {
|
||||
if _surr1 <= r1 && r1 < _surr2 && _surr2 <= r2 && r2 < _surr3 {
|
||||
return (r1-_surr1)<<10 | (r2 - _surr2) + _surr_self;
|
||||
}
|
||||
@@ -19,7 +19,7 @@ decode_surrogate_pair :: proc(r1, r2: rune) -> rune {
|
||||
}
|
||||
|
||||
|
||||
encode_surrogate_pair :: proc(r: rune) -> (r1, r2: rune) {
|
||||
const encode_surrogate_pair = proc(r: rune) -> (r1, r2: rune) {
|
||||
if r < _surr_self || r > MAX_RUNE {
|
||||
return REPLACEMENT_CHAR, REPLACEMENT_CHAR;
|
||||
}
|
||||
@@ -27,15 +27,15 @@ encode_surrogate_pair :: proc(r: rune) -> (r1, r2: rune) {
|
||||
return _surr1 + (r>>10)&0x3ff, _surr2 + r&0x3ff;
|
||||
}
|
||||
|
||||
encode :: proc(d: []u16, s: []rune) {
|
||||
n := len(s);
|
||||
const encode = proc(d: []u16, s: []rune) {
|
||||
var n = len(s);
|
||||
for r in s {
|
||||
if r >= _surr_self {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
|
||||
max_n := min(len(d), n);
|
||||
var max_n = min(len(d), n);
|
||||
n = 0;
|
||||
|
||||
for r in s {
|
||||
@@ -45,7 +45,7 @@ encode :: proc(d: []u16, s: []rune) {
|
||||
n++;
|
||||
|
||||
case _surr_self..MAX_RUNE:
|
||||
r1, r2 := encode_surrogate_pair(r);
|
||||
var r1, r2 = encode_surrogate_pair(r);
|
||||
d[n] = u16(r1);
|
||||
d[n+1] = u16(r2);
|
||||
n += 2;
|
||||
|
||||
142
core/utf8.odin
142
core/utf8.odin
@@ -1,36 +1,36 @@
|
||||
RUNE_ERROR :: '\ufffd';
|
||||
RUNE_SELF :: 0x80;
|
||||
RUNE_BOM :: 0xfeff;
|
||||
RUNE_EOF :: ~rune(0);
|
||||
MAX_RUNE :: '\U0010ffff';
|
||||
UTF_MAX :: 4;
|
||||
const RUNE_ERROR = '\ufffd';
|
||||
const RUNE_SELF = 0x80;
|
||||
const RUNE_BOM = 0xfeff;
|
||||
const RUNE_EOF = ~rune(0);
|
||||
const MAX_RUNE = '\U0010ffff';
|
||||
const UTF_MAX = 4;
|
||||
|
||||
SURROGATE_MIN :: 0xd800;
|
||||
SURROGATE_MAX :: 0xdfff;
|
||||
const SURROGATE_MIN = 0xd800;
|
||||
const SURROGATE_MAX = 0xdfff;
|
||||
|
||||
T1 :: 0b0000_0000;
|
||||
TX :: 0b1000_0000;
|
||||
T2 :: 0b1100_0000;
|
||||
T3 :: 0b1110_0000;
|
||||
T4 :: 0b1111_0000;
|
||||
T5 :: 0b1111_1000;
|
||||
const T1 = 0b0000_0000;
|
||||
const TX = 0b1000_0000;
|
||||
const T2 = 0b1100_0000;
|
||||
const T3 = 0b1110_0000;
|
||||
const T4 = 0b1111_0000;
|
||||
const T5 = 0b1111_1000;
|
||||
|
||||
MASKX :: 0b0011_1111;
|
||||
MASK2 :: 0b0001_1111;
|
||||
MASK3 :: 0b0000_1111;
|
||||
MASK4 :: 0b0000_0111;
|
||||
const MASKX = 0b0011_1111;
|
||||
const MASK2 = 0b0001_1111;
|
||||
const MASK3 = 0b0000_1111;
|
||||
const MASK4 = 0b0000_0111;
|
||||
|
||||
RUNE1_MAX :: 1<<7 - 1;
|
||||
RUNE2_MAX :: 1<<11 - 1;
|
||||
RUNE3_MAX :: 1<<16 - 1;
|
||||
const RUNE1_MAX = 1<<7 - 1;
|
||||
const RUNE2_MAX = 1<<11 - 1;
|
||||
const RUNE3_MAX = 1<<16 - 1;
|
||||
|
||||
// The default lowest and highest continuation byte.
|
||||
LOCB :: 0b1000_0000;
|
||||
HICB :: 0b1011_1111;
|
||||
const LOCB = 0b1000_0000;
|
||||
const HICB = 0b1011_1111;
|
||||
|
||||
AcceptRange :: struct { lo, hi: u8 }
|
||||
const AcceptRange = struct { lo, hi: u8 }
|
||||
|
||||
immutable accept_ranges := [5]AcceptRange{
|
||||
immutable var accept_ranges = [5]AcceptRange{
|
||||
{0x80, 0xbf},
|
||||
{0xa0, 0xbf},
|
||||
{0x80, 0x9f},
|
||||
@@ -38,7 +38,7 @@ immutable accept_ranges := [5]AcceptRange{
|
||||
{0x80, 0x8f},
|
||||
};
|
||||
|
||||
immutable accept_sizes := [256]u8{
|
||||
immutable var accept_sizes = [256]u8{
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x00-0x0f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x10-0x1f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x20-0x2f
|
||||
@@ -58,10 +58,10 @@ immutable accept_sizes := [256]u8{
|
||||
0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff
|
||||
};
|
||||
|
||||
encode_rune :: proc(r: rune) -> ([4]u8, int) {
|
||||
buf: [4]u8;
|
||||
i := u32(r);
|
||||
mask: u8 : 0x3f;
|
||||
const encode_rune = proc(r: rune) -> ([4]u8, int) {
|
||||
var buf: [4]u8;
|
||||
var i = u32(r);
|
||||
const mask: u8 = 0x3f;
|
||||
if i <= 1<<7-1 {
|
||||
buf[0] = u8(r);
|
||||
return buf, 1;
|
||||
@@ -92,38 +92,38 @@ encode_rune :: proc(r: rune) -> ([4]u8, int) {
|
||||
return buf, 4;
|
||||
}
|
||||
|
||||
decode_rune :: proc(s: string) -> (rune, int) #inline { return decode_rune([]u8(s)); }
|
||||
decode_rune :: proc(s: []u8) -> (rune, int) {
|
||||
n := len(s);
|
||||
const decode_rune = proc(s: string) -> (rune, int) #inline { return decode_rune([]u8(s)); }
|
||||
const decode_rune = proc(s: []u8) -> (rune, int) {
|
||||
var n = len(s);
|
||||
if n < 1 {
|
||||
return RUNE_ERROR, 0;
|
||||
}
|
||||
s0 := s[0];
|
||||
x := accept_sizes[s0];
|
||||
var s0 = s[0];
|
||||
var x = accept_sizes[s0];
|
||||
if x >= 0xF0 {
|
||||
mask := rune(x) << 31 >> 31; // NOTE(bill): Create 0x0000 or 0xffff.
|
||||
var mask = rune(x) << 31 >> 31; // NOTE(bill): Create 0x0000 or 0xffff.
|
||||
return rune(s[0])&~mask | RUNE_ERROR&mask, 1;
|
||||
}
|
||||
sz := x & 7;
|
||||
accept := accept_ranges[x>>4];
|
||||
var sz = x & 7;
|
||||
var accept = accept_ranges[x>>4];
|
||||
if n < int(sz) {
|
||||
return RUNE_ERROR, 1;
|
||||
}
|
||||
b1 := s[1];
|
||||
var b1 = s[1];
|
||||
if b1 < accept.lo || accept.hi < b1 {
|
||||
return RUNE_ERROR, 1;
|
||||
}
|
||||
if sz == 2 {
|
||||
return rune(s0&MASK2)<<6 | rune(b1&MASKX), 2;
|
||||
}
|
||||
b2 := s[2];
|
||||
var b2 = s[2];
|
||||
if b2 < LOCB || HICB < b2 {
|
||||
return RUNE_ERROR, 1;
|
||||
}
|
||||
if sz == 3 {
|
||||
return rune(s0&MASK3)<<12 | rune(b1&MASKX)<<6 | rune(b2&MASKX), 3;
|
||||
}
|
||||
b3 := s[3];
|
||||
var b3 = s[3];
|
||||
if b3 < LOCB || HICB < b3 {
|
||||
return RUNE_ERROR, 1;
|
||||
}
|
||||
@@ -132,11 +132,11 @@ decode_rune :: proc(s: []u8) -> (rune, int) {
|
||||
|
||||
|
||||
|
||||
decode_last_rune :: proc(s: string) -> (rune, int) #inline { return decode_last_rune([]u8(s)); }
|
||||
decode_last_rune :: proc(s: []u8) -> (rune, int) {
|
||||
r: rune;
|
||||
size: int;
|
||||
start, end, limit: int;
|
||||
const decode_last_rune = proc(s: string) -> (rune, int) #inline { return decode_last_rune([]u8(s)); }
|
||||
const decode_last_rune = proc(s: []u8) -> (rune, int) {
|
||||
var r: rune;
|
||||
var size: int;
|
||||
var start, end, limit: int;
|
||||
|
||||
end = len(s);
|
||||
if end == 0 {
|
||||
@@ -171,7 +171,7 @@ decode_last_rune :: proc(s: []u8) -> (rune, int) {
|
||||
|
||||
|
||||
|
||||
valid_rune :: proc(r: rune) -> bool {
|
||||
const valid_rune = proc(r: rune) -> bool {
|
||||
if r < 0 {
|
||||
return false;
|
||||
} else if SURROGATE_MIN <= r && r <= SURROGATE_MAX {
|
||||
@@ -182,32 +182,32 @@ valid_rune :: proc(r: rune) -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
valid_string :: proc(s: string) -> bool {
|
||||
n := len(s);
|
||||
for i := 0; i < n; {
|
||||
si := s[i];
|
||||
const valid_string = proc(s: string) -> bool {
|
||||
var n = len(s);
|
||||
for var i = 0; i < n; {
|
||||
var si = s[i];
|
||||
if si < RUNE_SELF { // ascii
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
x := accept_sizes[si];
|
||||
var x = accept_sizes[si];
|
||||
if x == 0xf1 {
|
||||
return false;
|
||||
}
|
||||
size := int(x & 7);
|
||||
var size = int(x & 7);
|
||||
if i+size > n {
|
||||
return false;
|
||||
}
|
||||
ar := accept_ranges[x>>4];
|
||||
if b := s[i+1]; b < ar.lo || ar.hi < b {
|
||||
var ar = accept_ranges[x>>4];
|
||||
if var b = s[i+1]; b < ar.lo || ar.hi < b {
|
||||
return false;
|
||||
} else if size == 2 {
|
||||
// Okay
|
||||
} else if b := s[i+2]; b < 0x80 || 0xbf < b {
|
||||
} else if var b = s[i+2]; b < 0x80 || 0xbf < b {
|
||||
return false;
|
||||
} else if size == 3 {
|
||||
// Okay
|
||||
} else if b := s[i+3]; b < 0x80 || 0xbf < b {
|
||||
} else if var b = s[i+3]; b < 0x80 || 0xbf < b {
|
||||
return false;
|
||||
}
|
||||
i += size;
|
||||
@@ -215,40 +215,40 @@ valid_string :: proc(s: string) -> bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
rune_start :: proc(b: u8) -> bool #inline { return b&0xc0 != 0x80; }
|
||||
const rune_start = proc(b: u8) -> bool #inline { return b&0xc0 != 0x80; }
|
||||
|
||||
rune_count :: proc(s: string) -> int #inline { return rune_count([]u8(s)); }
|
||||
rune_count :: proc(s: []u8) -> int {
|
||||
count := 0;
|
||||
n := len(s);
|
||||
const rune_count = proc(s: string) -> int #inline { return rune_count([]u8(s)); }
|
||||
const rune_count = proc(s: []u8) -> int {
|
||||
var count = 0;
|
||||
var n = len(s);
|
||||
|
||||
for i := 0; i < n; {
|
||||
for var i = 0; i < n; {
|
||||
defer count++;
|
||||
si := s[i];
|
||||
var si = s[i];
|
||||
if si < RUNE_SELF { // ascii
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
x := accept_sizes[si];
|
||||
var x = accept_sizes[si];
|
||||
if x == 0xf1 {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
size := int(x & 7);
|
||||
var size = int(x & 7);
|
||||
if i+size > n {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
ar := accept_ranges[x>>4];
|
||||
if b := s[i+1]; b < ar.lo || ar.hi < b {
|
||||
var ar = accept_ranges[x>>4];
|
||||
if var b = s[i+1]; b < ar.lo || ar.hi < b {
|
||||
size = 1;
|
||||
} else if size == 2 {
|
||||
// Okay
|
||||
} else if b := s[i+2]; b < 0x80 || 0xbf < b {
|
||||
} else if var b = s[i+2]; b < 0x80 || 0xbf < b {
|
||||
size = 1;
|
||||
} else if size == 3 {
|
||||
// Okay
|
||||
} else if b := s[i+3]; b < 0x80 || 0xbf < b {
|
||||
} else if var b = s[i+3]; b < 0x80 || 0xbf < b {
|
||||
size = 1;
|
||||
}
|
||||
i += size;
|
||||
@@ -257,7 +257,7 @@ rune_count :: proc(s: []u8) -> int {
|
||||
}
|
||||
|
||||
|
||||
rune_size :: proc(r: rune) -> int {
|
||||
const rune_size = proc(r: rune) -> int {
|
||||
match {
|
||||
case r < 0: return -1;
|
||||
case r <= 1<<7 - 1: return 1;
|
||||
|
||||
@@ -1538,7 +1538,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
case_ast_node(vd, ValueDecl, node);
|
||||
GB_ASSERT(!c->context.scope->is_file);
|
||||
if (!vd->is_var) {
|
||||
if (vd->token.kind != Token_var) {
|
||||
// NOTE(bill): Handled elsewhere
|
||||
} else {
|
||||
Entity **entities = gb_alloc_array(c->allocator, Entity *, vd->names.count);
|
||||
|
||||
@@ -1451,7 +1451,7 @@ void check_collect_entities(Checker *c, Array<AstNode *> nodes, bool is_file_sco
|
||||
case_end;
|
||||
|
||||
case_ast_node(vd, ValueDecl, decl);
|
||||
if (vd->is_var) {
|
||||
if (vd->token.kind == Token_var) {
|
||||
if (!c->context.scope->is_file) {
|
||||
// NOTE(bill): local scope -> handle later and in order
|
||||
break;
|
||||
|
||||
@@ -5813,7 +5813,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(vd, ValueDecl, node);
|
||||
if (vd->is_var) {
|
||||
if (vd->token.kind == Token_var) {
|
||||
irModule *m = proc->module;
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||
|
||||
|
||||
@@ -298,11 +298,11 @@ AST_NODE_KIND(_StmtEnd, "", i32) \
|
||||
AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||
AST_NODE_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \
|
||||
AST_NODE_KIND(ValueDecl, "value declaration", struct { \
|
||||
bool is_var; \
|
||||
Token token; \
|
||||
Array<AstNode *> names; \
|
||||
AstNode * type; \
|
||||
AstNode * type; \
|
||||
Array<AstNode *> values; \
|
||||
u32 flags; \
|
||||
u32 flags; \
|
||||
}) \
|
||||
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
|
||||
Token token; \
|
||||
@@ -525,10 +525,10 @@ Token ast_node_token(AstNode *node) {
|
||||
case AstNode_PushContext: return node->PushContext.token;
|
||||
|
||||
case AstNode_BadDecl: return node->BadDecl.begin;
|
||||
case AstNode_ValueDecl: return ast_node_token(node->ValueDecl.names[0]);
|
||||
case AstNode_ValueDecl: return node->ValueDecl.token;
|
||||
case AstNode_ImportDecl: return node->ImportDecl.token;
|
||||
case AstNode_ForeignLibrary: return node->ForeignLibrary.token;
|
||||
case AstNode_Label: return node->Label.token;
|
||||
case AstNode_Label: return node->Label.token;
|
||||
|
||||
|
||||
case AstNode_Field:
|
||||
@@ -1412,9 +1412,9 @@ AstNode *ast_map_type(AstFile *f, Token token, AstNode *count, AstNode *key, Ast
|
||||
}
|
||||
|
||||
|
||||
AstNode *ast_value_decl(AstFile *f, bool is_var, Array<AstNode *> names, AstNode *type, Array<AstNode *> values) {
|
||||
AstNode *ast_value_decl(AstFile *f, Token token, Array<AstNode *> names, AstNode *type, Array<AstNode *> values) {
|
||||
AstNode *result = make_ast_node(f, AstNode_ValueDecl);
|
||||
result->ValueDecl.is_var = is_var;
|
||||
result->ValueDecl.token = token;
|
||||
result->ValueDecl.names = names;
|
||||
result->ValueDecl.type = type;
|
||||
result->ValueDecl.values = values;
|
||||
@@ -1646,7 +1646,7 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
||||
return s->ProcLit.body != NULL;
|
||||
|
||||
case AstNode_ValueDecl:
|
||||
if (!s->ValueDecl.is_var) {
|
||||
if (s->ValueDecl.token.kind != Token_var) {
|
||||
if (s->ValueDecl.values.count > 0) {
|
||||
AstNode *last = s->ValueDecl.values[s->ValueDecl.values.count-1];
|
||||
return is_semicolon_optional_for_node(f, last);
|
||||
@@ -2023,6 +2023,11 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
||||
return ast_paren_expr(f, operand, open, close);
|
||||
}
|
||||
|
||||
case Token_type: {
|
||||
Token token = expect_token(f, Token_type);
|
||||
return ast_helper_type(f, token, parse_type(f));
|
||||
}
|
||||
|
||||
case Token_Hash: {
|
||||
Token token = expect_token(f, Token_Hash);
|
||||
Token name = expect_token(f, Token_Ident);
|
||||
@@ -2037,7 +2042,6 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
||||
} else if (name.string == "file") { return ast_basic_directive(f, token, name.string);
|
||||
} else if (name.string == "line") { return ast_basic_directive(f, token, name.string);
|
||||
} else if (name.string == "procedure") { return ast_basic_directive(f, token, name.string);
|
||||
} else if (name.string == "type") { return ast_helper_type(f, token, parse_type(f));
|
||||
} else if (!lhs && name.string == "alias") { return ast_alias(f, token, parse_expr(f, false));
|
||||
} else {
|
||||
operand = ast_tag_expr(f, token, name, parse_expr(f, false));
|
||||
@@ -2476,13 +2480,14 @@ AstNode *parse_type(AstFile *f) {
|
||||
}
|
||||
|
||||
|
||||
AstNode *parse_value_decl(AstFile *f, Array<AstNode *> lhs) {
|
||||
AstNode *parse_value_decl(AstFile *f, Token token) {
|
||||
Array<AstNode *> lhs = parse_lhs_expr_list(f);
|
||||
AstNode *type = NULL;
|
||||
Array<AstNode *> values = {};
|
||||
bool is_mutable = true;
|
||||
bool is_mutable = token.kind == Token_var;
|
||||
|
||||
if (allow_token(f, Token_Colon)) {
|
||||
type = parse_type_attempt(f);
|
||||
type = parse_type(f);
|
||||
} else if (f->curr_token.kind != Token_Eq &&
|
||||
f->curr_token.kind != Token_Semicolon) {
|
||||
syntax_error(f->curr_token, "Expected a type separator `:` or `=`");
|
||||
@@ -2490,9 +2495,6 @@ AstNode *parse_value_decl(AstFile *f, Array<AstNode *> lhs) {
|
||||
|
||||
|
||||
switch (f->curr_token.kind) {
|
||||
case Token_Colon:
|
||||
is_mutable = false;
|
||||
/*fallthrough*/
|
||||
case Token_Eq:
|
||||
next_token(f);
|
||||
values = parse_rhs_expr_list(f);
|
||||
@@ -2524,14 +2526,25 @@ AstNode *parse_value_decl(AstFile *f, Array<AstNode *> lhs) {
|
||||
|
||||
Array<AstNode *> specs = {};
|
||||
array_init(&specs, heap_allocator(), 1);
|
||||
return ast_value_decl(f, is_mutable, lhs, type, values);
|
||||
// Token token = ast_node_token(lhs[0]);
|
||||
// token.kind = is_mutable ? Token_var : Token_const;
|
||||
// token.string = is_mutable ? str_lit("var") : str_lit("const");
|
||||
return ast_value_decl(f, token, lhs, type, values);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) {
|
||||
Array<AstNode *> lhs = parse_lhs_expr_list(f);
|
||||
Token token = f->curr_token;
|
||||
switch (f->curr_token.kind) {
|
||||
case Token_var:
|
||||
case Token_const:
|
||||
next_token(f);
|
||||
return parse_value_decl(f, token);
|
||||
}
|
||||
|
||||
Array<AstNode *> lhs = parse_lhs_expr_list(f);
|
||||
token = f->curr_token;
|
||||
switch (token.kind) {
|
||||
case Token_Eq:
|
||||
case Token_AddEq:
|
||||
@@ -2604,7 +2617,7 @@ AstNode *parse_simple_stmt(AstFile *f, StmtAllowFlag flags) {
|
||||
}
|
||||
}
|
||||
|
||||
return parse_value_decl(f, lhs);
|
||||
// return parse_value_decl(f, lhs);
|
||||
}
|
||||
|
||||
if (lhs.count > 1) {
|
||||
@@ -3621,6 +3634,13 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
|
||||
case Token_var:
|
||||
case Token_const:
|
||||
s = parse_simple_stmt(f, StmtAllowFlag_None);
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
|
||||
|
||||
case Token_if: return parse_if_stmt(f);
|
||||
case Token_when: return parse_when_stmt(f);
|
||||
case Token_for: return parse_for_stmt(f);
|
||||
@@ -3659,12 +3679,15 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
return ast_using_stmt(f, token, list);
|
||||
}
|
||||
|
||||
AstNode *decl = parse_value_decl(f, list);
|
||||
Token var = ast_node_token(list[0]);
|
||||
var.kind = Token_var;
|
||||
var.string = str_lit("var");
|
||||
AstNode *decl = parse_value_decl(f, var);
|
||||
expect_semicolon(f, decl);
|
||||
|
||||
if (decl->kind == AstNode_ValueDecl) {
|
||||
#if 1
|
||||
if (!decl->ValueDecl.is_var) {
|
||||
if (decl->ValueDecl.token.kind != Token_var) {
|
||||
syntax_error(token, "`using` may not be applied to constant declarations");
|
||||
return decl;
|
||||
}
|
||||
@@ -3689,7 +3712,7 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
AstNode *node = parse_stmt(f);
|
||||
|
||||
if (node->kind == AstNode_ValueDecl) {
|
||||
if (!node->ValueDecl.is_var) {
|
||||
if (node->ValueDecl.token.kind != Token_var) {
|
||||
syntax_error(token, "`immutable` may not be applied to constant declarations");
|
||||
} else {
|
||||
node->ValueDecl.flags |= VarDeclFlag_immutable;
|
||||
@@ -3861,7 +3884,7 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
AstNode *s = parse_stmt(f);
|
||||
|
||||
if (s->kind == AstNode_ValueDecl) {
|
||||
if (!s->ValueDecl.is_var) {
|
||||
if (s->ValueDecl.token.kind != Token_var) {
|
||||
syntax_error(token, "`thread_local` may not be applied to constant declarations");
|
||||
}
|
||||
if (f->curr_proc != NULL) {
|
||||
|
||||
@@ -1969,7 +1969,7 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(vd, ValueDecl, node);
|
||||
if (vd->is_var) {
|
||||
if (vd->token.kind == Token_var) {
|
||||
ssaModule *m = p->module;
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||
if (vd->values.count == 0) {
|
||||
|
||||
@@ -82,6 +82,9 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
|
||||
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
|
||||
\
|
||||
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
||||
TOKEN_KIND(Token_var, "var"), \
|
||||
TOKEN_KIND(Token_const, "const"), \
|
||||
TOKEN_KIND(Token_type, "type"), \
|
||||
TOKEN_KIND(Token_when, "when"), \
|
||||
TOKEN_KIND(Token_if, "if"), \
|
||||
TOKEN_KIND(Token_else, "else"), \
|
||||
|
||||
Reference in New Issue
Block a user