diff --git a/base/runtime/dynamic_map_internal.odin b/base/runtime/dynamic_map_internal.odin index 6955f4a1e..642a6fb18 100644 --- a/base/runtime/dynamic_map_internal.odin +++ b/base/runtime/dynamic_map_internal.odin @@ -391,7 +391,8 @@ map_alloc_dynamic :: proc "odin" (info: ^Map_Info, log2_capacity: uintptr, alloc // arrays to reduce variance. This swapping can only be done with memcpy since // there is no type information. // -// This procedure returns the address of the just inserted value. +// This procedure returns the address of the just inserted value, and will +// return 'nil' if there was no room to insert the entry @(require_results) map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: Map_Hash, ik: uintptr, iv: uintptr) -> (result: uintptr) { h := h @@ -415,6 +416,11 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^ tv := map_cell_index_dynamic(sv, info.vs, 1) swap_loop: for { + if distance > mask { + // Failed to find an empty slot and prevent infinite loop + panic("unable to insert into a map") + } + element_hash := hs[pos] if map_hash_is_empty(element_hash) { @@ -898,7 +904,9 @@ __dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_In } result := map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(value)) - m.len += 1 + if result != 0 { + m.len += 1 + } return rawptr(result) } __dynamic_map_set_extra_without_hash :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> (prev_key_ptr, value_ptr: rawptr) { @@ -921,7 +929,9 @@ __dynamic_map_set_extra :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^ } result := map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(value)) - m.len += 1 + if result != 0 { + m.len += 1 + } return nil, rawptr(result) } diff --git a/core/mem/mutex_allocator.odin b/core/mem/mutex_allocator.odin index bf69c9b81..591703eab 100644 --- a/core/mem/mutex_allocator.odin +++ b/core/mem/mutex_allocator.odin @@ -3,19 +3,19 @@ package mem import "core:sync" -Mutex_allocator :: struct { +Mutex_Allocator :: struct { backing: Allocator, mutex: sync.Mutex, } -mutex_allocator_init :: proc(m: ^Mutex_allocator, backing_allocator: Allocator) { +mutex_allocator_init :: proc(m: ^Mutex_Allocator, backing_allocator: Allocator) { m.backing = backing_allocator m.mutex = {} } @(require_results) -mutex_allocator :: proc(m: ^Mutex_allocator) -> Allocator { +mutex_allocator :: proc(m: ^Mutex_Allocator) -> Allocator { return Allocator{ procedure = mutex_allocator_proc, data = m, @@ -25,7 +25,7 @@ mutex_allocator :: proc(m: ^Mutex_allocator) -> Allocator { mutex_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location) -> (result: []byte, err: Allocator_Error) { - m := (^Mutex_allocator)(allocator_data) + m := (^Mutex_Allocator)(allocator_data) sync.mutex_guard(&m.mutex) return m.backing.procedure(m.backing.data, mode, size, alignment, old_memory, old_size, loc) diff --git a/core/os/os2/file.odin b/core/os/os2/file.odin index 1b98ae1dd..0efa53537 100644 --- a/core/os/os2/file.odin +++ b/core/os/os2/file.odin @@ -6,6 +6,7 @@ import "base:runtime" File :: struct { impl: _File, + stream: io.Stream, } File_Mode :: distinct u32 @@ -72,56 +73,56 @@ name :: proc(f: ^File) -> string { close :: proc(f: ^File) -> Error { if f != nil { - return io.close(f.impl.stream) + return io.close(f.stream) } return nil } seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) { if f != nil { - return io.seek(f.impl.stream, offset, whence) + return io.seek(f.stream, offset, whence) } return 0, .Invalid_File } read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { if f != nil { - return io.read(f.impl.stream, p) + return io.read(f.stream, p) } return 0, .Invalid_File } read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { if f != nil { - return io.read_at(f.impl.stream, p, offset) + return io.read_at(f.stream, p, offset) } return 0, .Invalid_File } write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) { if f != nil { - return io.write(f.impl.stream, p) + return io.write(f.stream, p) } return 0, .Invalid_File } write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) { if f != nil { - return io.write_at(f.impl.stream, p, offset) + return io.write_at(f.stream, p, offset) } return 0, .Invalid_File } file_size :: proc(f: ^File) -> (n: i64, err: Error) { if f != nil { - return io.size(f.impl.stream) + return io.size(f.stream) } return 0, .Invalid_File } flush :: proc(f: ^File) -> Error { if f != nil { - return io.flush(f.impl.stream) + return io.flush(f.stream) } return nil } diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin index d5626791f..61d320184 100644 --- a/core/os/os2/file_linux.odin +++ b/core/os/os2/file_linux.odin @@ -33,8 +33,6 @@ _File :: struct { name: string, fd: int, allocator: runtime.Allocator, - - stream: io.Stream, } _file_allocator :: proc() -> runtime.Allocator { @@ -75,7 +73,7 @@ _new_file :: proc(fd: uintptr, _: string) -> ^File { file.impl.fd = int(fd) file.impl.allocator = _file_allocator() file.impl.name = _get_full_path(file.impl.fd, file.impl.allocator) - file.impl.stream = { + file.stream = { data = file, procedure = _file_stream_proc, } diff --git a/core/os/os2/file_stream.odin b/core/os/os2/file_stream.odin index da1e3344f..84176928d 100644 --- a/core/os/os2/file_stream.odin +++ b/core/os/os2/file_stream.odin @@ -4,8 +4,8 @@ import "core:io" to_stream :: proc(f: ^File) -> (s: io.Stream) { if f != nil { - assert(f.impl.stream.procedure != nil) - s = f.impl.stream + assert(f.stream.procedure != nil) + s = f.stream } return } diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index eae7b6372..8cb040a0a 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -73,8 +73,6 @@ _File :: struct { wname: win32.wstring, kind: _File_Kind, - stream: io.Stream, - allocator: runtime.Allocator, rw_mutex: sync.RW_Mutex, // read write calls @@ -181,7 +179,7 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File { } f.impl.kind = kind - f.impl.stream = { + f.stream = { data = f, procedure = _file_stream_proc, } diff --git a/core/slice/slice.odin b/core/slice/slice.odin index 88f8cb799..dd8d9868a 100644 --- a/core/slice/slice.odin +++ b/core/slice/slice.odin @@ -497,8 +497,8 @@ unique :: proc(s: $S/[]$T) -> S where intrinsics.type_is_comparable(T) #no_bound for j in 1.. bool) -> S #no_bounds_check { for j in 1.. c.int { - return cast(c.int)intrinsics.syscall(unix_offset_syscall(.mmap), uintptr(addr), uintptr(len)) + return cast(c.int)intrinsics.syscall(unix_offset_syscall(.munmap), uintptr(addr), uintptr(len)) } syscall_mmap :: #force_inline proc "contextless" (addr: ^u8, len: u64, port: c.int, flags: c.int, fd: int, offset: off_t) -> ^u8 { @@ -417,3 +417,7 @@ syscall_chdir :: #force_inline proc "contextless" (path: cstring) -> c.int { syscall_fchdir :: #force_inline proc "contextless" (fd: c.int, path: cstring) -> c.int { return cast(c.int)intrinsics.syscall(unix_offset_syscall(.getentropy), uintptr(fd), transmute(uintptr)path) } + +syscall_getrusage :: #force_inline proc "contextless" (who: c.int, rusage: ^RUsage) -> c.int { + return cast(c.int) intrinsics.syscall(unix_offset_syscall(.getrusage), uintptr(who), uintptr(rusage)) +} diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 0911e48cf..b58006427 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -108,7 +108,7 @@ gb_internal Type *make_soa_struct_dynamic_array(CheckerContext *ctx, Ast *array_ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 id, Type *type_hint); -gb_internal void check_promote_optional_ok(CheckerContext *c, Operand *x, Type **val_type_, Type **ok_type_); +gb_internal void check_promote_optional_ok(CheckerContext *c, Operand *x, Type **val_type_, Type **ok_type_, bool change_operand=true); gb_internal void check_or_else_right_type(CheckerContext *c, Ast *expr, String const &name, Type *right_type); gb_internal void check_or_else_split_types(CheckerContext *c, Operand *x, String const &name, Type **left_type_, Type **right_type_); @@ -1539,7 +1539,25 @@ gb_internal Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *nam if (is_blank_ident(name)) { error(n, "'_' cannot be used as a value"); } else { + ERROR_BLOCK(); error(n, "Undeclared name: %.*s", LIT(name)); + + // NOTE(bill): Loads of checks for C programmers + if (name == "float") { + error_line("\tSuggestion: Did you mean 'f32'?\n"); + } else if (name == "double") { + error_line("\tSuggestion: Did you mean 'f64'?\n"); + } else if (name == "short") { + error_line("\tSuggestion: Did you mean 'i16' or 'c.short' (which is part of 'core:c')?\n"); + } else if (name == "long") { + error_line("\tSuggestion: Did you mean 'c.long' (which is part of 'core:c')?\n"); + } else if (name == "unsigned") { + error_line("\tSuggestion: Did you mean 'c.uint' (which is part of 'core:c')?\n"); + } else if (name == "char") { + error_line("\tSuggestion: Did you mean 'u8', 'i8' or 'c.char' (which is part of 'core:c')?\n"); + } else if (name == "while") { + error_line("\tSuggestion: Did you mean 'for'? Odin only has one loop construct: 'for'\n"); + } } o->type = t_invalid; o->mode = Addressing_Invalid; @@ -6796,7 +6814,7 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O isize index = lookup_polymorphic_record_parameter(original_type, name); if (index >= 0) { TypeTuple *params = get_record_polymorphic_params(original_type); - Entity *e = params->variables[i]; + Entity *e = params->variables[index]; if (e->kind == Entity_Constant) { check_expr_with_type_hint(c, &operands[i], fv->value, e->type); continue; @@ -6847,7 +6865,7 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O Array ordered_operands = operands; if (!named_fields) { - ordered_operands = array_make(permanent_allocator(), param_count); + ordered_operands = array_make(permanent_allocator(), operands.count); array_copy(&ordered_operands, operands, 0); } else { TEMPORARY_ALLOCATOR_GUARD(); @@ -7801,7 +7819,7 @@ gb_internal ExprKind check_implicit_selector_expr(CheckerContext *c, Operand *o, } -gb_internal void check_promote_optional_ok(CheckerContext *c, Operand *x, Type **val_type_, Type **ok_type_) { +gb_internal void check_promote_optional_ok(CheckerContext *c, Operand *x, Type **val_type_, Type **ok_type_, bool change_operand) { switch (x->mode) { case Addressing_MapIndex: case Addressing_OptionalOk: @@ -7819,22 +7837,28 @@ gb_internal void check_promote_optional_ok(CheckerContext *c, Operand *x, Type * Type *pt = base_type(type_of_expr(expr->CallExpr.proc)); if (is_type_proc(pt)) { Type *tuple = pt->Proc.results; - add_type_and_value(c, x->expr, x->mode, tuple, x->value); if (pt->Proc.result_count >= 2) { if (ok_type_) *ok_type_ = tuple->Tuple.variables[1]->type; } - expr->CallExpr.optional_ok_one = false; - x->type = tuple; + if (change_operand) { + expr->CallExpr.optional_ok_one = false; + x->type = tuple; + add_type_and_value(c, x->expr, x->mode, tuple, x->value); + } return; } } Type *tuple = make_optional_ok_type(x->type); + if (ok_type_) *ok_type_ = tuple->Tuple.variables[1]->type; - add_type_and_value(c, x->expr, x->mode, tuple, x->value); - x->type = tuple; - GB_ASSERT(is_type_tuple(type_of_expr(x->expr))); + + if (change_operand) { + add_type_and_value(c, x->expr, x->mode, tuple, x->value); + x->type = tuple; + GB_ASSERT(is_type_tuple(type_of_expr(x->expr))); + } } @@ -8405,6 +8429,7 @@ gb_internal ExprKind check_or_branch_expr(CheckerContext *c, Operand *o, Ast *no switch (be->token.kind) { case Token_or_break: + node->viral_state_flags |= ViralStateFlag_ContainsOrBreak; if ((c->stmt_flags & Stmt_BreakAllowed) == 0 && label == nullptr) { error(be->token, "'%.*s' only allowed in non-inline loops or 'switch' statements", LIT(name)); } @@ -8478,18 +8503,26 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slicefield->kind != Ast_Ident) { - gbString expr_str = expr_to_string(fv->field); + Ast *ident = fv->field; + if (ident->kind == Ast_ImplicitSelectorExpr) { + gbString expr_str = expr_to_string(ident); + error(ident, "Field names do not start with a '.', remove the '.' in structure literal", expr_str); + gb_string_free(expr_str); + + ident = ident->ImplicitSelectorExpr.selector; + } + if (ident->kind != Ast_Ident) { + gbString expr_str = expr_to_string(ident); error(elem, "Invalid field name '%s' in structure literal", expr_str); gb_string_free(expr_str); continue; } - String name = fv->field->Ident.token.string; + String name = ident->Ident.token.string; Selection sel = lookup_field(type, name, o->mode == Addressing_Type); bool is_unknown = sel.entity == nullptr; if (is_unknown) { - error(fv->field, "Unknown field '%.*s' in structure literal", LIT(name)); + error(ident, "Unknown field '%.*s' in structure literal", LIT(name)); continue; } @@ -8503,24 +8536,24 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slicefield, field); + add_entity_use(c, ident, field); if (string_set_update(&fields_visited, name)) { if (sel.index.count > 1) { if (String *found = string_map_get(&fields_visited_through_raw_union, sel.entity->token.string)) { - error(fv->field, "Field '%.*s' is already initialized due to a previously assigned struct #raw_union field '%.*s'", LIT(sel.entity->token.string), LIT(*found)); + error(ident, "Field '%.*s' is already initialized due to a previously assigned struct #raw_union field '%.*s'", LIT(sel.entity->token.string), LIT(*found)); } else { - error(fv->field, "Duplicate or reused field '%.*s' in %.*s", LIT(sel.entity->token.string), LIT(assignment_str)); + error(ident, "Duplicate or reused field '%.*s' in %.*s", LIT(sel.entity->token.string), LIT(assignment_str)); } } else { - error(fv->field, "Duplicate field '%.*s' in %.*s", LIT(field->token.string), LIT(assignment_str)); + error(ident, "Duplicate field '%.*s' in %.*s", LIT(field->token.string), LIT(assignment_str)); } continue; } else if (String *found = string_map_get(&fields_visited_through_raw_union, sel.entity->token.string)) { - error(fv->field, "Field '%.*s' is already initialized due to a previously assigned struct #raw_union field '%.*s'", LIT(sel.entity->token.string), LIT(*found)); + error(ident, "Field '%.*s' is already initialized due to a previously assigned struct #raw_union field '%.*s'", LIT(sel.entity->token.string), LIT(*found)); continue; } if (sel.indirect) { - error(fv->field, "Cannot assign to the %d-nested anonymous indirect field '%.*s' in a %.*s", cast(int)sel.index.count-1, LIT(name), LIT(assignment_str)); + error(ident, "Cannot assign to the %d-nested anonymous indirect field '%.*s' in a %.*s", cast(int)sel.index.count-1, LIT(name), LIT(assignment_str)); continue; } @@ -10254,6 +10287,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast case_end; case_ast_node(re, OrReturnExpr, node); + node->viral_state_flags |= ViralStateFlag_ContainsOrReturn; return check_or_return_expr(c, o, node, type_hint); case_end; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index a7dd9743b..a6ca4b9dd 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -221,6 +221,12 @@ gb_internal bool check_has_break(Ast *stmt, String const &label, bool implicit) return true; } break; + + case Ast_ExprStmt: + if (stmt->ExprStmt.expr->viral_state_flags & ViralStateFlag_ContainsOrBreak) { + return true; + } + break; } return false; @@ -1537,8 +1543,16 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) goto skip_expr_range_stmt; } } else if (operand.mode != Addressing_Invalid) { + if (operand.mode == Addressing_OptionalOk || operand.mode == Addressing_OptionalOkPtr) { + Type *end_type = nullptr; + check_promote_optional_ok(ctx, &operand, nullptr, &end_type, false); + if (is_type_boolean(end_type)) { + check_promote_optional_ok(ctx, &operand, nullptr, &end_type, true); + } + } bool is_ptr = is_type_pointer(operand.type); Type *t = base_type(type_deref(operand.type)); + switch (t->kind) { case Type_Basic: if (t->Basic.kind == Basic_string || t->Basic.kind == Basic_UntypedString) { diff --git a/src/check_type.cpp b/src/check_type.cpp index dd77031a3..e71b35809 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1272,7 +1272,7 @@ gb_internal void check_bit_set_type(CheckerContext *c, Type *type, Type *named_t } if (!is_valid) { if (actual_lower != lower) { - error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required (internal the lower changed was changed 0 as an underlying type was set)", bits, bits_required); + error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required (internally the lower bound was changed to 0 as an underlying type was set)", bits, bits_required); } else { error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required", bits, bits_required); } @@ -1342,7 +1342,7 @@ gb_internal void check_bit_set_type(CheckerContext *c, Type *type, Type *named_t if (upper - lower >= bits) { i64 bits_required = upper-lower+1; if (lower_changed) { - error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required (internal the lower changed was changed 0 as an underlying type was set)", bits, bits_required); + error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required (internally the lower bound was changed to 0 as an underlying type was set)", bits, bits_required); } else { error(bs->elem, "bit_set range is greater than %lld bits, %lld bits are required", bits, bits_required); } diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 741557efd..6000be32d 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -508,7 +508,7 @@ gb_internal lbValue lb_dynamic_map_reserve(lbProcedure *p, lbValue const &map_pt gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e); gb_internal lbValue lb_find_value_from_entity(lbModule *m, Entity *e); -gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value); +gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value, bool is_default_case); gb_internal lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValue value); gb_internal lbValue lb_emit_source_code_location_const(lbProcedure *p, String const &procedure, TokenPos const &pos); gb_internal lbValue lb_const_source_code_location_const(lbModule *m, String const &procedure, TokenPos const &pos); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 09de90dc9..3c6a51bdc 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1515,9 +1515,11 @@ gb_internal String lb_set_nested_type_name_ir_mangled_name(Entity *e, lbProcedur GB_ASSERT(scope->flags & ScopeFlag_Proc); proc = scope->procedure_entity; } - GB_ASSERT(proc->kind == Entity_Procedure); - if (proc->code_gen_procedure != nullptr) { - p = proc->code_gen_procedure; + if (proc != nullptr) { + GB_ASSERT(proc->kind == Entity_Procedure); + if (proc->code_gen_procedure != nullptr) { + p = proc->code_gen_procedure; + } } } diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 0de9c0bf9..4ecf70ec4 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1454,7 +1454,7 @@ gb_internal void lb_build_switch_stmt(lbProcedure *p, AstSwitchStmt *ss, Scope * lb_close_scope(p, lbDeferExit_Default, done); } -gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value) { +gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValue value, bool is_default_case) { Entity *e = implicit_entity_of_node(clause); GB_ASSERT(e != nullptr); if (e->flags & EntityFlag_Value) { @@ -1463,8 +1463,9 @@ gb_internal void lb_store_type_case_implicit(lbProcedure *p, Ast *clause, lbValu lbAddr x = lb_add_local(p, e->type, e, false); lb_addr_store(p, x, value); } else { - // by reference - GB_ASSERT(are_types_identical(e->type, type_deref(value.type))); + if (!is_default_case) { + GB_ASSERT_MSG(are_types_identical(e->type, type_deref(value.type)), "%s %s", type_to_string(e->type), type_to_string(value.type)); + } lb_add_entity(p->module, e, value); } } @@ -1622,7 +1623,7 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss lb_open_scope(p, cc->scope); if (cc->list.count == 0) { lb_start_block(p, default_block); - lb_store_type_case_implicit(p, clause, parent_value); + lb_store_type_case_implicit(p, clause, parent_value, true); lb_type_case_body(p, ss->label, clause, p->curr_block, done); continue; } @@ -1688,7 +1689,7 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss lb_add_entity(p->module, case_entity, ptr); lb_add_debug_local_variable(p, ptr.value, case_entity->type, case_entity->token); } else { - lb_store_type_case_implicit(p, clause, parent_value); + lb_store_type_case_implicit(p, clause, parent_value, false); } lb_type_case_body(p, ss->label, clause, body, done); diff --git a/src/parser.hpp b/src/parser.hpp index f410419d4..f5997c4bd 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -310,6 +310,8 @@ enum StateFlag : u8 { enum ViralStateFlag : u8 { ViralStateFlag_ContainsDeferredProcedure = 1<<0, + ViralStateFlag_ContainsOrBreak = 1<<1, + ViralStateFlag_ContainsOrReturn = 1<<2, }; diff --git a/src/path.cpp b/src/path.cpp index 742bba7f8..b07f20870 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -407,7 +407,7 @@ gb_internal ReadDirectoryError read_directory(String path, Array *fi) i64 size = dir_stat.st_size; FileInfo info = {}; - info.name = name; + info.name = copy_string(a, name); info.fullpath = path_to_full_path(a, filepath); info.size = size; array_add(fi, info); diff --git a/vendor/cgltf/cgltf.odin b/vendor/cgltf/cgltf.odin index f432d0f0c..024e8dfaa 100644 --- a/vendor/cgltf/cgltf.odin +++ b/vendor/cgltf/cgltf.odin @@ -1,9 +1,9 @@ -//+build windows package cgltf -when ODIN_OS == .Windows { - foreign import lib "lib/cgltf.lib" -} +when ODIN_OS == .Windows { foreign import lib "lib/cgltf.lib" } +else when ODIN_OS == .Linux { foreign import lib "lib/cgltf.a" } +else when ODIN_OS == .Darwin { foreign import lib "lib/darwin/cgltf.a" } +else { foreign import lib "system:cgltf" } import "core:c" diff --git a/vendor/cgltf/src/Makefile b/vendor/cgltf/src/Makefile new file mode 100644 index 000000000..ede3d158e --- /dev/null +++ b/vendor/cgltf/src/Makefile @@ -0,0 +1,20 @@ +OS=$(shell uname) + +ifeq ($(OS), Darwin) +all: darwin +else +all: unix +endif + +unix: + mkdir -p ../lib + $(CC) -c -O2 -Os -fPIC cgltf.c + $(AR) rcs ../lib/cgltf.a cgltf.o + rm *.o + +darwin: + mkdir -p ../lib/darwin + $(CC) -arch x86_64 -c -O2 -Os -fPIC cgltf.c -o cgltf-x86_64.o -mmacosx-version-min=10.12 + $(CC) -arch arm64 -c -O2 -Os -fPIC cgltf.c -o cgltf-arm64.o -mmacosx-version-min=10.12 + lipo -create cgltf-x86_64.o cgltf-arm64.o -output ../lib/darwin/cgltf.a + rm *.o