diff options
| author | gingerBill <gingerBill@users.noreply.github.com> | 2017-02-01 20:31:57 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-02-01 20:31:57 +0000 |
| commit | c6133587d1bdf7ae723beb8c3a3b27b472bf2d7a (patch) | |
| tree | fd080deab099e74ec5f50841c6a8b5b5b8b5c3c4 | |
| parent | 4e7082a68dd5261c3c36eccf92a62a0ce84995a8 (diff) | |
| parent | 5516e80ab775d1100beca7847e10520eae4b151c (diff) | |
Merge pull request #16 from zhiayang/master
Basic, but sketchy, but somewhat usable, non-windows support
| -rw-r--r-- | code/old_demos/demo001.odin | 33 | ||||
| -rw-r--r-- | code/test.odin | 6 | ||||
| -rw-r--r-- | core/os.odin | 1 | ||||
| -rw-r--r-- | core/os_x.odin | 230 | ||||
| -rw-r--r-- | src/build.c | 92 | ||||
| -rw-r--r-- | src/check_decl.c | 2 | ||||
| -rw-r--r-- | src/check_expr.c | 6 | ||||
| -rw-r--r-- | src/check_stmt.c | 1 | ||||
| -rw-r--r-- | src/checker.c | 48 | ||||
| -rw-r--r-- | src/entity.c | 61 | ||||
| -rw-r--r-- | src/exact_value.c | 1 | ||||
| -rw-r--r-- | src/gb/gb.h | 23 | ||||
| -rw-r--r-- | src/main.c | 63 | ||||
| -rw-r--r-- | src/parser.c | 1 | ||||
| -rw-r--r-- | src/string.c | 61 | ||||
| -rw-r--r-- | src/timings.c | 36 | ||||
| -rw-r--r-- | src/types.c | 2 |
17 files changed, 577 insertions, 90 deletions
diff --git a/code/old_demos/demo001.odin b/code/old_demos/demo001.odin index 7e80f0d1b..c3fc0f663 100644 --- a/code/old_demos/demo001.odin +++ b/code/old_demos/demo001.odin @@ -6,21 +6,24 @@ // #import "punity.odin" as pn; main :: proc() { - // struct_padding() - // bounds_checking() - // type_introspection() - // any_type() - // crazy_introspection() - // namespaces_and_files() - // miscellany() - // ht.run() - // game.run() - // { - // init :: proc(c: ^pn.Core) {} - // step :: proc(c: ^pn.Core) {} - - // pn.run(init, step) - // } + struct_padding(); + bounds_checking(); + type_introspection(); + any_type(); + crazy_introspection(); + namespaces_and_files(); + miscellany(); + + /* + ht.run(); + game.run(); + { + init :: proc(c: ^pn.Core) {} + step :: proc(c: ^pn.Core) {} + + pn.run(init, step); + } + */ } struct_padding :: proc() { diff --git a/code/test.odin b/code/test.odin index 18fc36c16..bcd4ddc57 100644 --- a/code/test.odin +++ b/code/test.odin @@ -5,10 +5,10 @@ thing :: proc() { }*/ -#import "fmt.odin" as format +#import "fmt.odin"; -thing :: proc() { - format.println("Hello2!") +main :: proc() { + fmt.println("hello, world!"); } diff --git a/core/os.odin b/core/os.odin index 2a44b8a88..0ce897bd7 100644 --- a/core/os.odin +++ b/core/os.odin @@ -1,2 +1,3 @@ #include "os_windows.odin" when ODIN_OS == "windows"; +#include "os_x.odin" when ODIN_OS == "osx"; diff --git a/core/os_x.odin b/core/os_x.odin new file mode 100644 index 000000000..f18c78c1c --- /dev/null +++ b/core/os_x.odin @@ -0,0 +1,230 @@ +#import "fmt.odin"; + +Handle :: i32; +File_Time :: u64; +Errno :: int; + +// 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; + +// 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; + +// Windows reserves errors >= 1<<29 for application use +// ERROR_FILE_IS_PIPE: Errno : 1<<29 + 0; + +#foreign_system_library libc "c"; + +unix_open :: proc(path: ^u8, mode: int, perm: u32) -> Handle #foreign libc "open"; +unix_close :: proc(handle: Handle) #foreign libc "close"; +unix_read :: proc(handle: Handle, buffer: rawptr, count: int) -> int #foreign libc "read"; +unix_write :: proc(handle: Handle, buffer: rawptr, count: int) -> int #foreign libc "write"; +unix_gettid :: proc() -> u64 #foreign libc "gettid"; + +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_exit :: proc(status: int) #foreign libc "exit"; + + + + +open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) { + return unix_open(path.data, mode, perm), 0; +} + +close :: proc(fd: Handle) { + unix_close(fd); +} + +write :: proc(fd: Handle, data: []byte) -> (int, Errno) { + return unix_write(fd, data.data, data.count), 0; +} + +read :: proc(fd: Handle, data: []byte) -> (int, Errno) { + return unix_read(fd, data.data, data.count), 0; +} + +seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) { + /* + using win32; + w: u32; + match whence { + case 0: w = FILE_BEGIN; + case 1: w = FILE_CURRENT; + case 2: w = FILE_END; + } + hi := cast(i32)(offset>>32); + lo := cast(i32)(offset); + ft := GetFileType(cast(HANDLE)fd); + if ft == FILE_TYPE_PIPE { + return 0, ERROR_FILE_IS_PIPE; + } + dw_ptr := SetFilePointer(cast(HANDLE)fd, lo, ^hi, w); + if dw_ptr == INVALID_SET_FILE_POINTER { + err := GetLastError(); + return 0, cast(Errno)err; + } + return cast(i64)hi<<32 + cast(i64)dw_ptr, ERROR_NONE; + + */ + return 0, 0; +} + + +// 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); + + +/* +get_std_handle :: proc(h: int) -> Handle { + fd := win32.GetStdHandle(cast(i32)h); + win32.SetHandleInformation(fd, win32.HANDLE_FLAG_INHERIT, 0); + return cast(Handle)fd; +} + + + + + + +last_write_time :: proc(fd: Handle) -> File_Time { + file_info: win32.BY_HANDLE_FILE_INFORMATION; + win32.GetFileInformationByHandle(cast(win32.HANDLE)fd, ^file_info); + lo := cast(File_Time)file_info.last_write_time.lo; + hi := cast(File_Time)file_info.last_write_time.hi; + return lo | hi << 32; +} + +last_write_time_by_name :: proc(name: string) -> File_Time { + last_write_time: win32.FILETIME; + data: win32.FILE_ATTRIBUTE_DATA; + buf: [1024]byte; + + assert(buf.count > name.count); + + copy(buf[:], cast([]byte)name); + + if win32.GetFileAttributesExA(^buf[0], win32.GetFileExInfoStandard, ^data) != 0 { + last_write_time = data.last_write_time; + } + + l := cast(File_Time)last_write_time.lo; + h := cast(File_Time)last_write_time.hi; + return l | h << 32; +} + + + + + +read_entire_file :: proc(name: string) -> ([]byte, bool) { + buf: [300]byte; + copy(buf[:], cast([]byte)name); + + fd, err := open(name, O_RDONLY, 0); + if err != ERROR_NONE { + return nil, false; + } + defer close(fd); + + length: i64; + file_size_ok := win32.GetFileSizeEx(cast(win32.HANDLE)fd, ^length) != 0; + if !file_size_ok { + return nil, false; + } + + data := new_slice(u8, length); + if data.data == nil { + return nil, false; + } + + single_read_length: i32; + total_read: i64; + + for total_read < length { + remaining := length - total_read; + to_read: u32; + MAX :: 1<<32-1; + if remaining <= MAX { + to_read = cast(u32)remaining; + } else { + to_read = MAX; + } + + win32.ReadFile(cast(win32.HANDLE)fd, ^data[total_read], to_read, ^single_read_length, nil); + if single_read_length <= 0 { + free(data); + return nil, false; + } + + total_read += cast(i64)single_read_length; + } + + return data, true; +} + + +*/ + +heap_alloc :: proc(size: int) -> rawptr { + assert(size > 0); + return unix_malloc(size); +} +heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr { + return unix_realloc(ptr, new_size); +} +heap_free :: proc(ptr: rawptr) { + unix_free(ptr); +} + + +exit :: proc(code: int) { + unix_exit(code); +} + + +current_thread_id :: proc() -> int { + // return cast(int) unix_gettid(); + return 0; +} + + + diff --git a/src/build.c b/src/build.c index f929dcc6d..2b69b3718 100644 --- a/src/build.c +++ b/src/build.c @@ -22,6 +22,7 @@ typedef struct BuildContext { String const WIN32_SEPARATOR_STRING = {cast(u8 *)"\\", 1}; String const NIX_SEPARATOR_STRING = {cast(u8 *)"/", 1}; +#if defined(WINDOWS) String odin_root_dir(void) { String path = global_module_path; Array(wchar_t) path_buf; @@ -71,6 +72,83 @@ String odin_root_dir(void) { return path; } +#elif defined(GB_SYSTEM_OSX) + +#include <mach-o/dyld.h> + +String odin_root_dir(void) { + String path = global_module_path; + Array(char) path_buf; + isize len, i; + gbTempArenaMemory tmp; + wchar_t *text; + + if (global_module_path_set) { + return global_module_path; + } + + array_init_count(&path_buf, heap_allocator(), 300); + + len = 0; + for (;;) { + int sz = path_buf.count; + int res = _NSGetExecutablePath(&path_buf.e[0], &sz); + if(res == 0) { + len = sz; + break; + } else { + array_resize(&path_buf, sz + 1); + } + } + + + tmp = gb_temp_arena_memory_begin(&string_buffer_arena); + text = gb_alloc_array(string_buffer_allocator, u8, len + 1); + gb_memmove(text, &path_buf.e[0], len); + + path = make_string(text, len); + for (i = path.len-1; i >= 0; i--) { + u8 c = path.text[i]; + if (c == '/' || c == '\\') { + break; + } + path.len--; + } + + global_module_path = path; + global_module_path_set = true; + + gb_temp_arena_memory_end(tmp); + + // array_free(&path_buf); + + return path; +} +#else +#error Implement system +#endif + + + + + + + + + + + + + + + + + + + + + +#if defined(GB_SYSTEM_WINDOWS) String path_to_fullpath(gbAllocator a, String s) { gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena); String16 string16 = string_to_string16(string_buffer_allocator, s); @@ -86,6 +164,17 @@ String path_to_fullpath(gbAllocator a, String s) { gb_temp_arena_memory_end(tmp); return result; } +#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX) +String path_to_fullpath(gbAllocator a, String s) { + char* p = realpath(s.text, 0); + // GB_ASSERT(p && "file does not exist"); + if(!p) return make_string_c(""); + + return make_string(p, strlen(p)); +} +#else +#error Implement system +#endif String get_fullpath_relative(gbAllocator a, String base_dir, String path) { @@ -154,6 +243,9 @@ void init_build_context(BuildContext *bc) { #if defined(GB_SYSTEM_WINDOWS) bc->ODIN_OS = str_lit("windows"); bc->ODIN_ARCH = str_lit("amd64"); +#elif defined(GB_SYSTEM_OSX) + bc->ODIN_OS = str_lit("osx"); + bc->ODIN_ARCH = str_lit("amd64"); #else #error Implement system #endif diff --git a/src/check_decl.c b/src/check_decl.c index 51655d445..6233a0bc0 100644 --- a/src/check_decl.c +++ b/src/check_decl.c @@ -69,7 +69,7 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra AstNode *rhs = inits.e[i]; Operand o = {0}; check_multi_expr(c, &o, rhs); - if (o.type->kind != Type_Tuple) { + if (o.type == NULL || o.type->kind != Type_Tuple) { array_add(&operands, o); } else { TypeTuple *tuple = &o.type->Tuple; diff --git a/src/check_expr.c b/src/check_expr.c index c8b1c3175..6b09c3a82 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -225,6 +225,9 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) { return -1; } +#ifndef _MAX +#define _MAX(x, y) ((x) > (y) ? (x) : (y)) +#endif bool check_is_assignable_to_with_score(Checker *c, Operand *operand, Type *type, i64 *score_) { i64 score = 0; @@ -232,7 +235,8 @@ bool check_is_assignable_to_with_score(Checker *c, Operand *operand, Type *type, bool ok = distance >= 0; if (ok) { // TODO(bill): A decent score function - score = max(1000000 - distance*distance, 0); + // score = max(1000000 - distance*distance, 0); + score = _MAX(1000000 - distance*distance, 0); } if (score_) *score_ = score; return ok; diff --git a/src/check_stmt.c b/src/check_stmt.c index 8ff5c3b2e..470848115 100644 --- a/src/check_stmt.c +++ b/src/check_stmt.c @@ -724,6 +724,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) { } skip_expr: + ; // again, declaring a variable immediately after a label... weird. AstNode *lhs[2] = {rs->value, rs->index}; Type * rhs[2] = {val, idx}; diff --git a/src/checker.c b/src/checker.c index 7d3ca0d82..ef26b20c2 100644 --- a/src/checker.c +++ b/src/checker.c @@ -118,47 +118,6 @@ typedef enum StmtFlag { Stmt_GiveAllowed = 1<<3, } StmtFlag; -typedef enum BuiltinProcId { - BuiltinProc_Invalid, - - BuiltinProc_new, - BuiltinProc_new_slice, - BuiltinProc_free, - - BuiltinProc_reserve, - BuiltinProc_append, - - BuiltinProc_size_of, - BuiltinProc_size_of_val, - BuiltinProc_align_of, - BuiltinProc_align_of_val, - BuiltinProc_offset_of, - BuiltinProc_offset_of_val, - BuiltinProc_type_of_val, - - BuiltinProc_type_info, - BuiltinProc_type_info_of_val, - - BuiltinProc_compile_assert, - BuiltinProc_assert, - BuiltinProc_panic, - - BuiltinProc_copy, - // BuiltinProc_append, - - BuiltinProc_swizzle, - - // BuiltinProc_ptr_offset, - // BuiltinProc_ptr_sub, - BuiltinProc_slice_ptr, - - BuiltinProc_min, - BuiltinProc_max, - BuiltinProc_abs, - BuiltinProc_clamp, - - BuiltinProc_Count, -} BuiltinProcId; typedef struct BuiltinProc { String name; isize arg_count; @@ -205,13 +164,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = { {STR_LIT("clamp"), 3, false, Expr_Expr}, }; -typedef enum ImplicitValueId { - ImplicitValue_Invalid, - - ImplicitValue_context, - - ImplicitValue_Count, -} ImplicitValueId; typedef struct ImplicitValueInfo { String name; String backing_name; diff --git a/src/entity.c b/src/entity.c index 3ca709aa4..30ad8f053 100644 --- a/src/entity.c +++ b/src/entity.c @@ -1,8 +1,65 @@ typedef struct Scope Scope; typedef struct Checker Checker; typedef struct Type Type; -typedef enum BuiltinProcId BuiltinProcId; -typedef enum ImplicitValueId ImplicitValueId; +// typedef enum BuiltinProcId BuiltinProcId; +// typedef enum ImplicitValueId ImplicitValueId; + + + +typedef enum BuiltinProcId { + BuiltinProc_Invalid, + + BuiltinProc_new, + BuiltinProc_new_slice, + BuiltinProc_free, + + BuiltinProc_reserve, + BuiltinProc_append, + + BuiltinProc_size_of, + BuiltinProc_size_of_val, + BuiltinProc_align_of, + BuiltinProc_align_of_val, + BuiltinProc_offset_of, + BuiltinProc_offset_of_val, + BuiltinProc_type_of_val, + + BuiltinProc_type_info, + BuiltinProc_type_info_of_val, + + BuiltinProc_compile_assert, + BuiltinProc_assert, + BuiltinProc_panic, + + BuiltinProc_copy, + // BuiltinProc_append, + + BuiltinProc_swizzle, + + // BuiltinProc_ptr_offset, + // BuiltinProc_ptr_sub, + BuiltinProc_slice_ptr, + + BuiltinProc_min, + BuiltinProc_max, + BuiltinProc_abs, + BuiltinProc_clamp, + + BuiltinProc_Count, +} BuiltinProcId; + + +typedef enum ImplicitValueId { + ImplicitValue_Invalid, + + ImplicitValue_context, + + ImplicitValue_Count, +} ImplicitValueId; + + + + #define ENTITY_KINDS \ ENTITY_KIND(Invalid) \ diff --git a/src/exact_value.c b/src/exact_value.c index 83add68f4..7c48d126b 100644 --- a/src/exact_value.c +++ b/src/exact_value.c @@ -416,6 +416,7 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y) } error: + ; // MSVC accepts this??? apparently you cannot declare variables immediately after labels... ExactValue error_value = {0}; // gb_printf_err("Invalid binary operation: %s\n", token_kind_to_string(op)); return error_value; diff --git a/src/gb/gb.h b/src/gb/gb.h index 304f782b2..5d204605a 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -276,6 +276,8 @@ extern "C" { #include <stdarg.h> #include <stddef.h> + + #if defined(GB_SYSTEM_WINDOWS) #if !defined(GB_NO_WINDOWS_H) #define NOMINMAX 1 @@ -296,6 +298,7 @@ extern "C" { #include <errno.h> #include <fcntl.h> #include <pthread.h> + #define _IOSC11_SOURCE #include <stdlib.h> // NOTE(bill): malloc on linux #include <sys/mman.h> #if !defined(GB_SYSTEM_OSX) @@ -4819,14 +4822,17 @@ GB_ALLOCATOR_PROC(gb_heap_allocator_proc) { #else // TODO(bill): *nix version that's decent case gbAllocation_Alloc: { - ptr = aligned_alloc(alignment, size); + // ptr = aligned_alloc(alignment, size); + + posix_memalign(&ptr, alignment, size); + if (flags & gbAllocatorFlag_ClearToZero) { gb_zero_size(ptr, size); } } break; case gbAllocation_Free: { - free(gb_allocation_header(old_memory)); + // free(old_memory); } break; case gbAllocation_Resize: { @@ -7754,7 +7760,18 @@ char *gb_path_get_full_name(gbAllocator a, char const *path) { return gb_alloc_str_len(a, buf, len+1); #else // TODO(bill): Make work on *nix, etc. - return gb_alloc_str_len(a, path, gb_strlen(path)); + char* p = realpath(path, 0); + GB_ASSERT(p && "file does not exist"); + + isize len = gb_strlen(p); + + // bill... gb_alloc_str_len refused to work for this... + char* ret = gb_alloc(a, sizeof(char) * len + 1); + gb_memmove(ret, p, len); + ret[len] = 0; + free(p); + + return ret; #endif } diff --git a/src/main.c b/src/main.c index b35f399eb..4a2c3aaac 100644 --- a/src/main.c +++ b/src/main.c @@ -16,8 +16,10 @@ extern "C" { #include "ir_print.c" // #include "vm.c" +#if defined(GB_SYSTEM_WINDOWS) + // NOTE(bill): `name` is used in debugging and profiling modes -i32 win32_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) { +i32 system_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) { STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)}; PROCESS_INFORMATION pi = {0}; char cmd_line[4096] = {0}; @@ -59,6 +61,53 @@ i32 win32_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) { gb_temp_arena_memory_end(tmp); return exit_code; } +#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX) +i32 system_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) { + + char cmd_line[4096] = {0}; + isize cmd_len; + va_list va; + String cmd; + i32 exit_code = 0; + + va_start(va, fmt); + cmd_len = gb_snprintf_va(cmd_line, gb_size_of(cmd_line), fmt, va); + va_end(va); + + exit_code = system(cmd.text); + + // pid_t pid = fork(); + // int status = 0; + + // if(pid == 0) { + // // in child, pid == 0. + // int ret = execvp(cmd.text, (char* const*) cmd.text); + + // if(ret == -1) { + // gb_printf_err("Failed to execute command:\n\t%s\n", cmd_line); + + // // we're in the child, so returning won't do us any good -- just quit. + // exit(-1); + // } + + // // unreachable + // abort(); + // } else { + // // wait for child to finish, then we can continue cleanup + + // int s = 0; + // waitpid(pid, &s, 0); + + // status = WEXITSTATUS(s); + // } + + // exit_code = status; +} +#endif + + + + void print_usage_line(i32 indent, char *fmt, ...) { while (indent --> 0) { @@ -190,7 +239,7 @@ int main(int argc, char **argv) { // prof_print_all(); -#if 1 + #if 1 timings_start_section(&timings, str_lit("llvm-opt")); char const *output_name = ir_gen.output_file.filename; @@ -202,7 +251,7 @@ int main(int argc, char **argv) { i32 exit_code = 0; // For more passes arguments: http://llvm.org/docs/Passes.html - exit_code = win32_exec_command_line_app("llvm-opt", false, + exit_code = system_exec_command_line_app("llvm-opt", false, "\"%.*sbin/opt\" \"%s\" -o \"%.*s\".bc " "-mem2reg " "-memcpyopt " @@ -217,10 +266,10 @@ int main(int argc, char **argv) { return exit_code; } - #if 1 + #if 0 timings_start_section(&timings, str_lit("llvm-llc")); // For more arguments: http://llvm.org/docs/CommandGuide/llc.html - exit_code = win32_exec_command_line_app("llvm-llc", false, + exit_code = system_exec_command_line_app("llvm-llc", false, "\"%.*sbin/llc\" \"%.*s.bc\" -filetype=obj -O%d " "%.*s " // "-debug-pass=Arguments " @@ -255,7 +304,7 @@ int main(int argc, char **argv) { link_settings = "/ENTRY:mainCRTStartup"; } - exit_code = win32_exec_command_line_app("msvc-link", true, + exit_code = system_exec_command_line_app("msvc-link", true, "link \"%.*s\".obj -OUT:\"%.*s.%s\" %s " "/defaultlib:libcmt " "/nologo /incremental:no /opt:ref /subsystem:CONSOLE " @@ -273,7 +322,7 @@ int main(int argc, char **argv) { // timings_print_all(&timings); if (run_output) { - win32_exec_command_line_app("odin run", false, "%.*s.exe", cast(int)base_name_len, output_name); + system_exec_command_line_app("odin run", false, "%.*s.exe", cast(int)base_name_len, output_name); } #endif #endif diff --git a/src/parser.c b/src/parser.c index 4f058777e..33cfd1078 100644 --- a/src/parser.c +++ b/src/parser.c @@ -3731,6 +3731,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) { String import_rel_path = imported_file.rel_path; TokenPos pos = imported_file.pos; AstFile file = {0}; + ParseFileError err = init_ast_file(&file, import_path); if (err != ParseFile_None) { diff --git a/src/string.c b/src/string.c index 69dbf1b58..2f8da20a8 100644 --- a/src/string.c +++ b/src/string.c @@ -165,6 +165,54 @@ bool string_contains_char(String s, u8 c) { return false; } + + + + + + + + +#if defined(GB_SYSTEM_WINDOWS) + + int convert_multibyte_to_widechar(char* multibyte_input, int input_length, wchar_t* output, int output_size) + { + return MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, multibyte_input, input_length, output, output_size); + } + + int convert_widechar_to_multibyte(wchar_t* widechar_input, int input_length, char* output, int output_size) + { + return WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, widechar_input, input_length, output, output_size, NULL, NULL); + } +} +#elif defined(GB_SYSTEM_UNIX) || defined(GB_SYSTEM_OSX) + + #include <iconv.h> + + int convert_multibyte_to_widechar(char* multibyte_input, int input_length, wchar_t* output, int output_size) + { + iconv_t conv = iconv_open("WCHAR_T", "UTF-8"); + size_t result = iconv(conv, (char**) &multibyte_input, &input_length, (char**) &output, &output_size); + iconv_close(conv); + + return (int) result; + } + + int convert_widechar_to_multibyte(wchar_t* widechar_input, int input_length, char* output, int output_size) + { + iconv_t conv = iconv_open("UTF-8", "WCHAR_T"); + size_t result = iconv(conv, (char**) &widechar_input, &input_length, (char**) &output, &output_size); + iconv_close(conv); + + return (int) result; + } +#else +#error Implement system +#endif + + + + // TODO(bill): Make this non-windows specific String16 string_to_string16(gbAllocator a, String s) { int len, len1; @@ -174,16 +222,14 @@ String16 string_to_string16(gbAllocator a, String s) { return make_string16(NULL, 0); } - len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, - cast(char *)s.text, s.len, NULL, 0); + len = convert_multibyte_to_widechar(cast(char *)s.text, s.len, NULL, 0); if (len == 0) { return make_string16(NULL, 0); } text = gb_alloc_array(a, wchar_t, len+1); - len1 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, - cast(char *)s.text, s.len, text, len); + len1 = convert_multibyte_to_widechar(cast(char *)s.text, s.len, text, len); if (len1 == 0) { gb_free(a, text); return make_string16(NULL, 0); @@ -201,16 +247,14 @@ String string16_to_string(gbAllocator a, String16 s) { return make_string(NULL, 0); } - len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, - s.text, s.len, NULL, 0, NULL, NULL); + len = convert_widechar_to_multibyte(s.text, s.len, NULL, 0); if (len == 0) { return make_string(NULL, 0); } text = gb_alloc_array(a, u8, len+1); - len1 = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, - s.text, s.len, cast(char *)text, len, NULL, NULL); + len1 = convert_widechar_to_multibyte(s.text, s.len, cast(char *)text, len); if (len1 == 0) { gb_free(a, text); return make_string(NULL, 0); @@ -236,7 +280,6 @@ String string16_to_string(gbAllocator a, String16 s) { - bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *tail_string) { u8 c; diff --git a/src/timings.c b/src/timings.c index a934414ec..b31fd0738 100644 --- a/src/timings.c +++ b/src/timings.c @@ -11,6 +11,7 @@ typedef struct Timings { } Timings; +#if defined(GB_SYSTEM_WINDOWS) u64 win32_time_stamp_time_now(void) { LARGE_INTEGER counter; QueryPerformanceCounter(&counter); @@ -26,10 +27,43 @@ u64 win32_time_stamp__freq(void) { return win32_perf_count_freq.QuadPart; } +#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX) +#include <time.h> + +u64 unix_time_stamp_time_now(void) { + struct timespec ts; + clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + + return (ts.tv_sec * 1000000000) + ts.tv_nsec; +} + +u64 unix_time_stamp__freq(void) { + gb_local_persist u64 freq = 0; + + if (freq == 0) { + struct timespec ts; + clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts); + + // that would be an absurd resolution (or lack thereof) + GB_ASSERT(ts.tv_sec == 0); + + freq = cast(u64) ((1.0 / ts.tv_nsec) * 1000000000.0); + + GB_ASSERT(freq != 0); + } + + return freq; +} + +#else +#error Implement system +#endif u64 time_stamp_time_now(void) { #if defined(GB_SYSTEM_WINDOWS) return win32_time_stamp_time_now(); +#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX) + return unix_time_stamp_time_now(); #else #error time_stamp_time_now #endif @@ -38,6 +72,8 @@ u64 time_stamp_time_now(void) { u64 time_stamp__freq(void) { #if defined(GB_SYSTEM_WINDOWS) return win32_time_stamp__freq(); +#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX) + return unix_time_stamp__freq(); #else #error time_stamp__freq #endif diff --git a/src/types.c b/src/types.c index 185438c03..b3e96eb79 100644 --- a/src/types.c +++ b/src/types.c @@ -1348,7 +1348,7 @@ void type_path_pop(TypePath *tp) { i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t); i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t); -i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, i64 index); +i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, isize index); i64 type_size_of_internal (BaseTypeSizes s, gbAllocator allocator, Type *t, TypePath *path); i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypePath *path); |