Merge pull request #16 from zhiayang/master

Basic, but sketchy, but somewhat usable, non-windows support
This commit is contained in:
gingerBill
2017-02-01 20:31:57 +00:00
committed by GitHub
17 changed files with 576 additions and 89 deletions

View File

@@ -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) {}
struct_padding();
bounds_checking();
type_introspection();
any_type();
crazy_introspection();
namespaces_and_files();
miscellany();
// pn.run(init, step)
// }
/*
ht.run();
game.run();
{
init :: proc(c: ^pn.Core) {}
step :: proc(c: ^pn.Core) {}
pn.run(init, step);
}
*/
}
struct_padding :: proc() {

View File

@@ -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!");
}

View File

@@ -1,2 +1,3 @@
#include "os_windows.odin" when ODIN_OS == "windows";
#include "os_x.odin" when ODIN_OS == "osx";

230
core/os_x.odin Normal file
View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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};

View File

@@ -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;

View File

@@ -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) \

View File

@@ -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;

View File

@@ -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
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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

View File

@@ -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);