From 22e982c8fbec797f2fb48a7df5ab28efc0ee16c9 Mon Sep 17 00:00:00 2001 From: nakst Date: Mon, 2 Sep 2019 16:46:50 +0100 Subject: New Essence OS layer; cross-compiling improvements --- src/build_settings.cpp | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 992443f7c..956ffe1ed 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -56,8 +56,6 @@ TargetEndianKind target_endians[TargetArch_COUNT] = { String const ODIN_VERSION = str_lit("0.10.1"); -String cross_compile_target = str_lit(""); -String cross_compile_lib_dir = str_lit(""); @@ -66,6 +64,7 @@ struct TargetMetrics { TargetArchKind arch; isize word_size; isize max_align; + String target_triplet; }; @@ -109,6 +108,7 @@ struct BuildContext { bool has_resource; String opt_flags; String llc_flags; + String target_triplet; String link_flags; bool is_dll; bool generate_docs; @@ -121,6 +121,7 @@ struct BuildContext { bool no_crt; bool use_lld; bool vet; + bool cross_compiling; QueryDataSetSettings query_data_set_settings; @@ -135,18 +136,19 @@ struct BuildContext { gb_global BuildContext build_context = {0}; - gb_global TargetMetrics target_windows_386 = { TargetOs_windows, TargetArch_386, 4, 8, + str_lit("i686-pc-windows"), }; gb_global TargetMetrics target_windows_amd64 = { TargetOs_windows, TargetArch_amd64, 8, 16, + str_lit("x86_64-pc-windows-gnu"), }; gb_global TargetMetrics target_linux_386 = { @@ -154,12 +156,14 @@ gb_global TargetMetrics target_linux_386 = { TargetArch_386, 4, 8, + str_lit("i686-pc-linux-gnu"), }; gb_global TargetMetrics target_linux_amd64 = { TargetOs_linux, TargetArch_amd64, 8, 16, + str_lit("x86_64-pc-linux-gnu"), }; gb_global TargetMetrics target_osx_amd64 = { @@ -167,10 +171,32 @@ gb_global TargetMetrics target_osx_amd64 = { TargetArch_amd64, 8, 16, + str_lit("x86_64-apple-darwin"), +}; + +gb_global TargetMetrics target_essence_amd64 = { + TargetOs_essence, + TargetArch_amd64, + 8, + 16, + str_lit("x86_64-pc-none-elf"), }; +struct NamedTargetMetrics { + String name; + TargetMetrics *metrics; +}; +gb_global NamedTargetMetrics named_targets[] = { + { str_lit("essence_amd64"), &target_essence_amd64 }, + { str_lit("macos_amd64"), &target_osx_amd64 }, + { str_lit("linux_386"), &target_linux_386 }, + { str_lit("linux_amd64"), &target_linux_amd64 }, + { str_lit("windows_386"), &target_windows_386 }, + { str_lit("windows_amd64"), &target_windows_amd64 }, +}; +NamedTargetMetrics *selected_target_metrics; TargetOsKind get_target_os_from_string(String str) { for (isize i = 0; i < TargetOs_COUNT; i++) { @@ -522,7 +548,7 @@ String get_fullpath_core(gbAllocator a, String path) { -void init_build_context(void) { +void init_build_context(TargetMetrics *cross_target) { BuildContext *bc = &build_context; gb_affinity_init(&bc->affinity); @@ -554,8 +580,9 @@ void init_build_context(void) { #endif #endif - if (cross_compile_target.len) { - bc->ODIN_OS = cross_compile_target; + if (cross_target) { + metrics = *cross_target; + bc->cross_compiling = true; } GB_ASSERT(metrics.os != TargetOs_Invalid); @@ -573,6 +600,7 @@ void init_build_context(void) { bc->max_align = metrics.max_align; bc->link_flags = str_lit(" "); bc->opt_flags = str_lit(" "); + bc->target_triplet = metrics.target_triplet; gbString llc_flags = gb_string_make_reserve(heap_allocator(), 64); -- cgit v1.2.3 From 66ae4e5afc87e4804cf371b49cc68cbecf253373 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 1 Oct 2019 20:38:50 +0100 Subject: Change ODIN_OS string for osx from "osx" to "darwin" to allow for other platforms --- core/os/os_darwin.odin | 295 +++++++++++++++++++++++++++++++++++++++++++++ core/time/time_darwin.odin | 3 + core/time/time_osx.odin | 3 - src/build_settings.cpp | 16 +-- src/check_type.cpp | 2 +- src/ir_print.cpp | 14 ++- 6 files changed, 316 insertions(+), 17 deletions(-) create mode 100644 core/os/os_darwin.odin create mode 100644 core/time/time_darwin.odin delete mode 100644 core/time/time_osx.odin (limited to 'src/build_settings.cpp') diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin new file mode 100644 index 000000000..7b183b3aa --- /dev/null +++ b/core/os/os_darwin.odin @@ -0,0 +1,295 @@ +package os + +foreign import dl "system:dl" +foreign import libc "system:c" + +import "core:runtime" +import "core:strings" + +OS :: "darwin"; + +Handle :: distinct i32; +File_Time :: distinct u64; +Errno :: distinct int; + +INVALID_HANDLE :: ~Handle(0); + +O_RDONLY :: 0x00000; +O_WRONLY :: 0x00001; +O_RDWR :: 0x00002; +O_CREATE :: 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; + + + +// 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; + + +// "Argv" arguments converted to Odin strings +args := _alloc_command_line_arguments(); + +_File_Time :: struct { + seconds: i64, + nanoseconds: i64, +} + +Stat :: struct { + device_id: i32, // ID of device containing file + mode: u16, // Mode of the file + nlink: u16, // Number of hard links + serial: u64, // File serial number + uid: u32, // User ID of the file's owner + gid: u32, // Group ID of the file's group + rdev: i32, // Device ID, if device + + last_access: File_Time, // Time of last access + modified: File_Time, // Time of last modification + status_change: File_Time, // Time of last status change + created: File_Time, // Time of creation + + size: i64, // Size of the file, in bytes + blocks: i64, // Number of blocks allocated for the file + block_size: i32, // Optimal blocksize for I/O + flags: u32, // User-defined flags for the file + gen_num: u32, // File generation number ..? + _spare: i32, // RESERVED + _reserve1, + _reserve2: i64, // RESERVED +}; + +// File type +S_IFMT :: 0o170000; // Type of file mask +S_IFIFO :: 0o010000; // Named pipe (fifo) +S_IFCHR :: 0o020000; // Character special +S_IFDIR :: 0o040000; // Directory +S_IFBLK :: 0o060000; // Block special +S_IFREG :: 0o100000; // Regular +S_IFLNK :: 0o120000; // Symbolic link +S_IFSOCK :: 0o140000; // Socket + +// File mode +// Read, write, execute/search by owner +S_IRWXU :: 0o0700; // RWX mask for owner +S_IRUSR :: 0o0400; // R for owner +S_IWUSR :: 0o0200; // W for owner +S_IXUSR :: 0o0100; // X for owner + +// Read, write, execute/search by group +S_IRWXG :: 0o0070; // RWX mask for group +S_IRGRP :: 0o0040; // R for group +S_IWGRP :: 0o0020; // W for group +S_IXGRP :: 0o0010; // X for group + +// Read, write, execute/search by others +S_IRWXO :: 0o0007; // RWX mask for other +S_IROTH :: 0o0004; // R for other +S_IWOTH :: 0o0002; // W for other +S_IXOTH :: 0o0001; // X for other + +S_ISUID :: 0o4000; // Set user id on execution +S_ISGID :: 0o2000; // Set group id on execution +S_ISVTX :: 0o1000; // Directory restrcted delete + +S_ISLNK :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFLNK; +S_ISREG :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFREG; +S_ISDIR :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFDIR; +S_ISCHR :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFCHR; +S_ISBLK :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFBLK; +S_ISFIFO :: inline proc(m: u32) -> bool do return (m & S_IFMT) == S_IFIFO; +S_ISSOCK :: inline proc(m: u32) -> bool do 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 + +foreign libc { + @(link_name="open") _unix_open :: proc(path: cstring, flags: int, #c_vararg mode: ..any) -> Handle ---; + @(link_name="close") _unix_close :: proc(handle: Handle) ---; + @(link_name="read") _unix_read :: proc(handle: Handle, buffer: rawptr, count: int) -> int ---; + @(link_name="write") _unix_write :: proc(handle: Handle, buffer: rawptr, count: int) -> int ---; + @(link_name="lseek") _unix_lseek :: proc(fs: Handle, offset: int, whence: int) -> int ---; + @(link_name="gettid") _unix_gettid :: proc() -> u64 ---; + @(link_name="stat") _unix_stat :: proc(path: cstring, stat: ^Stat) -> int ---; + @(link_name="access") _unix_access :: proc(path: cstring, mask: int) -> int ---; + + @(link_name="malloc") _unix_malloc :: proc(size: int) -> rawptr ---; + @(link_name="calloc") _unix_calloc :: proc(num, size: int) -> rawptr ---; + @(link_name="free") _unix_free :: proc(ptr: rawptr) ---; + @(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr ---; + @(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---; + + @(link_name="exit") _unix_exit :: proc(status: int) ---; +} + +foreign dl { + @(link_name="dlopen") _unix_dlopen :: proc(filename: cstring, flags: int) -> rawptr ---; + @(link_name="dlsym") _unix_dlsym :: proc(handle: rawptr, symbol: cstring) -> rawptr ---; + @(link_name="dlclose") _unix_dlclose :: proc(handle: rawptr) -> int ---; + @(link_name="dlerror") _unix_dlerror :: proc() -> cstring ---; +} + +open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) { + cstr := strings.clone_to_cstring(path); + handle := _unix_open(cstr, flags, mode); + delete(cstr); + if handle == -1 { + return INVALID_HANDLE, 1; + } + return handle, 0; +} + +close :: proc(fd: Handle) { + _unix_close(fd); +} + +write :: proc(fd: Handle, data: []u8) -> (int, Errno) { + assert(fd != -1); + + 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) -> (int, Errno) { + assert(fd != -1); + + 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: i64, whence: int) -> (i64, Errno) { + assert(fd != -1); + + final_offset := i64(_unix_lseek(fd, int(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); + seek(fd, prev, SEEK_SET); + return i64(size), err; +} + + + +// 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); + +/* TODO(zangent): Implement these! +last_write_time :: proc(fd: Handle) -> File_Time {} +last_write_time_by_name :: proc(name: string) -> File_Time {} +*/ + +is_path_separator :: proc(r: rune) -> bool { + return r == '/'; +} + +stat :: inline proc(path: string) -> (Stat, bool) { + s: Stat; + cstr := strings.clone_to_cstring(path); + defer delete(cstr); + ret_int := _unix_stat(cstr, &s); + return s, ret_int==0; +} + +access :: inline proc(path: string, mask: int) -> bool { + cstr := strings.clone_to_cstring(path); + defer delete(cstr); + return _unix_access(cstr, mask) == 0; +} + +heap_alloc :: inline proc(size: int) -> rawptr { + assert(size > 0); + return _unix_calloc(1, size); +} +heap_resize :: inline proc(ptr: rawptr, new_size: int) -> rawptr { + return _unix_realloc(ptr, new_size); +} +heap_free :: inline proc(ptr: rawptr) { + _unix_free(ptr); +} + +getenv :: proc(name: string) -> (string, bool) { + path_str := strings.clone_to_cstring(name); + defer delete(path_str); + cstr := _unix_getenv(path_str); + if cstr == nil { + return "", false; + } + return string(cstr), true; +} + +exit :: inline proc(code: int) -> ! { + _unix_exit(code); +} + + +current_thread_id :: proc "contextless" () -> int { + // return int(_unix_gettid()); + return 0; +} + +dlopen :: inline proc(filename: string, flags: int) -> rawptr { + cstr := strings.clone_to_cstring(filename); + defer delete(cstr); + handle := _unix_dlopen(cstr, flags); + return handle; +} +dlsym :: inline proc(handle: rawptr, symbol: string) -> rawptr { + assert(handle != nil); + cstr := strings.clone_to_cstring(symbol); + defer delete(cstr); + proc_handle := _unix_dlsym(handle, cstr); + return proc_handle; +} +dlclose :: inline proc(handle: rawptr) -> bool { + assert(handle != nil); + return _unix_dlclose(handle) == 0; +} +dlerror :: proc() -> string { + return string(_unix_dlerror()); +} + + +_alloc_command_line_arguments :: proc() -> []string { + res := make([]string, len(runtime.args__)); + for arg, i in runtime.args__ { + res[i] = string(arg); + } + return res; +} diff --git a/core/time/time_darwin.odin b/core/time/time_darwin.odin new file mode 100644 index 000000000..7d1a1441c --- /dev/null +++ b/core/time/time_darwin.odin @@ -0,0 +1,3 @@ +package time + +IS_SUPPORTED :: false; \ No newline at end of file diff --git a/core/time/time_osx.odin b/core/time/time_osx.odin deleted file mode 100644 index 7d1a1441c..000000000 --- a/core/time/time_osx.odin +++ /dev/null @@ -1,3 +0,0 @@ -package time - -IS_SUPPORTED :: false; \ No newline at end of file diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 956ffe1ed..b4abf41a7 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -2,7 +2,7 @@ enum TargetOsKind { TargetOs_Invalid, TargetOs_windows, - TargetOs_osx, + TargetOs_darwin, TargetOs_linux, TargetOs_essence, @@ -30,7 +30,7 @@ enum TargetEndianKind { String target_os_names[TargetOs_COUNT] = { str_lit(""), str_lit("windows"), - str_lit("osx"), + str_lit("darwin"), str_lit("linux"), str_lit("essence"), }; @@ -166,8 +166,8 @@ gb_global TargetMetrics target_linux_amd64 = { str_lit("x86_64-pc-linux-gnu"), }; -gb_global TargetMetrics target_osx_amd64 = { - TargetOs_osx, +gb_global TargetMetrics target_darwin_amd64 = { + TargetOs_darwin, TargetArch_amd64, 8, 16, @@ -189,7 +189,7 @@ struct NamedTargetMetrics { gb_global NamedTargetMetrics named_targets[] = { { str_lit("essence_amd64"), &target_essence_amd64 }, - { str_lit("macos_amd64"), &target_osx_amd64 }, + { str_lit("darwin_amd64"), &target_darwin_amd64 }, { str_lit("linux_386"), &target_linux_386 }, { str_lit("linux_amd64"), &target_linux_amd64 }, { str_lit("windows_386"), &target_windows_386 }, @@ -566,7 +566,7 @@ void init_build_context(TargetMetrics *cross_target) { #if defined(GB_SYSTEM_WINDOWS) metrics = target_windows_amd64; #elif defined(GB_SYSTEM_OSX) - metrics = target_osx_amd64; + metrics = target_darwin_amd64; #else metrics = target_linux_amd64; #endif @@ -618,7 +618,7 @@ void init_build_context(TargetMetrics *cross_target) { case TargetOs_windows: bc->link_flags = str_lit("/machine:x64 "); break; - case TargetOs_osx: + case TargetOs_darwin: break; case TargetOs_linux: bc->link_flags = str_lit("-arch x86-64 "); @@ -631,7 +631,7 @@ void init_build_context(TargetMetrics *cross_target) { case TargetOs_windows: bc->link_flags = str_lit("/machine:x86 "); break; - case TargetOs_osx: + case TargetOs_darwin: gb_printf_err("Unsupported architecture\n"); gb_exit(1); break; diff --git a/src/check_type.cpp b/src/check_type.cpp index 465c11731..9f5ed0ed3 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1915,7 +1915,7 @@ Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type, ProcCall } } } else if (build_context.ODIN_OS == "linux" || - build_context.ODIN_OS == "osx") { + build_context.ODIN_OS == "darwin") { Type *bt = core_type(original_type); switch (bt->kind) { // Okay to pass by value (usually) diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 9414a2338..db9eb1bfb 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -1165,7 +1165,8 @@ void ir_print_calling_convention(irFileBuffer *f, irModule *m, ProcCallingConven switch (cc) { case ProcCC_Odin: ir_write_str_lit(f, ""); break; case ProcCC_Contextless: ir_write_str_lit(f, ""); break; - case ProcCC_CDecl: ir_write_str_lit(f, "ccc "); break; + // case ProcCC_CDecl: ir_write_str_lit(f, "ccc "); break; + case ProcCC_CDecl: ir_write_str_lit(f, ""); break; case ProcCC_StdCall: ir_write_str_lit(f, "cc 64 "); break; case ProcCC_FastCall: ir_write_str_lit(f, "cc 65 "); break; case ProcCC_None: ir_write_str_lit(f, ""); break; @@ -1175,8 +1176,8 @@ void ir_print_calling_convention(irFileBuffer *f, irModule *m, ProcCallingConven void ir_print_context_parameter_prefix(irFileBuffer *f, irModule *m) { ir_print_type(f, m, t_context_ptr); - ir_write_str_lit(f, " noalias nonnull nocapture inreg "); - // ir_write_str_lit(f, " noalias nonnull nocapture "); + // ir_write_str_lit(f, " noalias nonnull nocapture inreg "); + ir_write_str_lit(f, " noalias nonnull nocapture "); } void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { @@ -1227,6 +1228,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { ir_write_str_lit(f, ", "); ir_print_type(f, m, type); ir_fprintf(f, "* %%%d, align 1", instr->ZeroInit.address->index); + // ir_fprintf(f, "* %%%d", instr->ZeroInit.address->index); break; } @@ -2244,9 +2246,11 @@ void print_llvm_ir(irGen *ir) { defer (ir_file_buffer_destroy(f)); i32 word_bits = cast(i32)(8*build_context.word_size); - if (build_context.ODIN_OS == "osx" || build_context.ODIN_OS == "macos") { + if (build_context.ODIN_OS == "darwin") { GB_ASSERT(word_bits == 64); - ir_write_str_lit(f, "target triple = \"x86_64-apple-macosx10.8\"\n\n"); + ir_write_str_lit(f, "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"\n"); + ir_write_str_lit(f, "target triple = \"x86_64-apple-macosx10.8\"\n"); + ir_write_str_lit(f, "\n"); } else if (build_context.ODIN_OS == "windows") { ir_fprintf(f, "target triple = \"x86%s-pc-windows-msvc\"\n\n", word_bits == 64 ? "_64" : ""); if (word_bits == 64 && build_context.metrics.arch == TargetArch_amd64) { -- cgit v1.2.3 From 4e8a801b3504f402e06d6928e889b33c7872f88f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 6 Oct 2019 18:13:15 +0100 Subject: strings.split; strings.index; eprint* over print*_err; --- core/fmt/fmt.odin | 18 ++++-- core/reflect/types.odin | 6 +- core/runtime/core.odin | 4 +- core/strconv/strconv.odin | 4 ++ core/strings/builder.odin | 4 ++ core/strings/strings.odin | 150 +++++++++++++++++++++++++++++++++++++++++++++- examples/demo/demo.odin | 12 +++- src/build_settings.cpp | 2 +- 8 files changed, 183 insertions(+), 17 deletions(-) (limited to 'src/build_settings.cpp') diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index a2f1166ac..6903b9bdb 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -59,12 +59,18 @@ fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int { // print* procedures return the number of bytes written -print :: proc(args: ..any) -> int { return fprint(context.stdout, ..args); } -print_err :: proc(args: ..any) -> int { return fprint(context.stderr, ..args); } -println :: proc(args: ..any) -> int { return fprintln(context.stdout, ..args); } -println_err :: proc(args: ..any) -> int { return fprintln(context.stderr, ..args); } -printf :: proc(fmt: string, args: ..any) -> int { return fprintf(context.stdout, fmt, ..args); } -printf_err :: proc(fmt: string, args: ..any) -> int { return fprintf(context.stderr, fmt, ..args); } +print :: proc(args: ..any) -> int { return fprint(context.stdout, ..args); } +println :: proc(args: ..any) -> int { return fprintln(context.stdout, ..args); } +printf :: proc(fmt: string, args: ..any) -> int { return fprintf(context.stdout, fmt, ..args); } + +eprint :: proc(args: ..any) -> int { return fprint(context.stderr, ..args); } +eprintln :: proc(args: ..any) -> int { return fprintln(context.stderr, ..args); } +eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(context.stderr, fmt, ..args); } + + +@(deprecated="prefer eprint") print_err :: proc(args: ..any) -> int { return eprint(..args); } +@(deprecated="prefer eprintf") println_err :: proc(args: ..any) -> int { return eprintln(..args); } +@(deprecated="prefer eprintln") printf_err :: proc(fmt: string, args: ..any) -> int { return eprintf(fmt, ..args); } // aprint* procedures return a string that was allocated with the current context diff --git a/core/reflect/types.odin b/core/reflect/types.odin index 8130668b3..d1678a1b2 100644 --- a/core/reflect/types.odin +++ b/core/reflect/types.odin @@ -304,10 +304,8 @@ write_type :: proc(buf: ^strings.Builder, ti: ^rt.Type_Info) { write_byte(buf, info.signed ? 'i' : 'u'); write_i64(buf, i64(8*ti.size), 10); switch info.endianness { - case rt.Type_Info_Endianness.Little: - write_string(buf, "le"); - case rt.Type_Info_Endianness.Big: - write_string(buf, "be"); + case .Little: write_string(buf, "le"); + case .Big: write_string(buf, "be"); } } case rt.Type_Info_Rune: diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 022a84e9e..c401dbdf3 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -40,7 +40,7 @@ Type_Info_Enum_Value :: union { u8, u16, u32, u64, uint, uintptr, }; -Type_Info_Endianness :: enum u8 { +Platform_Endianness :: enum u8 { Platform = 0, Little = 1, Big = 2, @@ -48,7 +48,7 @@ Type_Info_Endianness :: enum u8 { // Variant Types Type_Info_Named :: struct {name: string, base: ^Type_Info}; -Type_Info_Integer :: struct {signed: bool, endianness: Type_Info_Endianness}; +Type_Info_Integer :: struct {signed: bool, endianness: Platform_Endianness}; Type_Info_Rune :: struct {}; Type_Info_Float :: struct {}; Type_Info_Complex :: struct {}; diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index ac78f78dc..447178bc3 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -205,7 +205,11 @@ itoa :: proc(buf: []byte, i: int) -> string { atoi :: proc(s: string) -> int { return parse_int(s); } +atof :: proc(s: string) -> f64 { + return parse_f64(s); +} +ftoa :: append_float; append_float :: proc(buf: []byte, f: f64, fmt: byte, prec, bit_size: int) -> string { return string(generic_ftoa(buf, f, fmt, prec, bit_size)); } diff --git a/core/strings/builder.odin b/core/strings/builder.odin index 68f1a7ceb..f7dac04ba 100644 --- a/core/strings/builder.odin +++ b/core/strings/builder.odin @@ -21,6 +21,10 @@ grow_builder :: proc(b: ^Builder, cap: int) { reserve(&b.buf, cap); } +reset_builder :: proc(b: ^Builder) { + clear(&b.buf); +} + builder_from_slice :: proc(backing: []byte) -> Builder { s := transmute(mem.Raw_Slice)backing; d := mem.Raw_Dynamic_Array{ diff --git a/core/strings/strings.odin b/core/strings/strings.odin index 8f9db86be..0c9ffa7d3 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -155,6 +155,73 @@ concatenate :: proc(a: []string, allocator := context.allocator) -> string { return string(b); } +@private +_split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocator) -> []string { + s, n := s_, n_; + + if n == 0 { + return nil; + } + + if sep == "" { + l := utf8.rune_count_in_string(s); + if n < 0 || n > l { + n = l; + } + + res := make([dynamic]string, n); + for i := 0; i < n-1; i += 1 { + r, w := utf8.decode_rune_in_string(s); + res[i] = s[:w]; + s = s[w:]; + } + if n > 0 { + res[n-1] = s; + } + return res[:]; + } + + if n < 0 { + n = count(s, sep) + 1; + } + + res := make([dynamic]string, n); + + n -= 1; + + i := 0; + for ; i < n; i += 1 { + m := index(s, sep); + if m < 0 { + break; + } + res[i] = s[:m+sep_save]; + s = s[m+len(sep):]; + } + res[i] = s; + + return res[:i+1]; +} + +split :: inline proc(s, sep: string, allocator := context.allocator) -> []string { + return _split(s, sep, 0, -1, allocator); +} + +split_n :: inline proc(s, sep: string, n: int, allocator := context.allocator) -> []string { + return _split(s, sep, 0, n, allocator); +} + +split_after :: inline proc(s, sep: string, allocator := context.allocator) -> []string { + return _split(s, sep, len(sep), -1, allocator); +} + +split_after_n :: inline proc(s, sep: string, n: int, allocator := context.allocator) -> []string { + return _split(s, sep, len(sep), n, allocator); +} + + + + index_byte :: proc(s: string, c: byte) -> int { for i := 0; i < len(s); i += 1 { if s[i] == c do return i; @@ -170,7 +237,25 @@ last_index_byte :: proc(s: string, c: byte) -> int { return -1; } + + +@private PRIME_RABIN_KARP :: 16777619; + index :: proc(s, substr: string) -> int { + hash_str_rabin_karp :: proc(s: string) -> (hash: u32 = 0, pow: u32 = 1) { + for i := 0; i < len(s); i += 1 { + hash = hash*PRIME_RABIN_KARP + u32(s[i]); + } + sq := u32(PRIME_RABIN_KARP); + for i := len(s); i > 0; i >>= 1 { + if (i & 1) != 0 { + pow *= sq; + } + sq *= sq; + } + return; + } + n := len(substr); switch { case n == 0: @@ -186,9 +271,68 @@ index :: proc(s, substr: string) -> int { return -1; } - for i := 0; i < len(s)-n+1; i += 1 { - x := s[i:i+n]; - if x == substr { + hash, pow := hash_str_rabin_karp(substr); + h: u32; + for i := 0; i < n; i += 1 { + h = h*PRIME_RABIN_KARP + u32(s[i]); + } + if h == hash && s[:n] == substr { + return 0; + } + for i := n; i < len(s); /**/ { + h *= PRIME_RABIN_KARP; + h += u32(s[i]); + h -= pow * u32(s[i-n]); + i += 1; + if h == hash && s[i-n:i] == substr { + return i - n; + } + } + return -1; +} + +last_index :: proc(s, substr: string) -> int { + hash_str_rabin_karp_reverse :: proc(s: string) -> (hash: u32 = 0, pow: u32 = 1) { + for i := len(s) - 1; i >= 0; i -= 1 { + hash = hash*PRIME_RABIN_KARP + u32(s[i]); + } + sq := u32(PRIME_RABIN_KARP); + for i := len(s); i > 0; i >>= 1 { + if (i & 1) != 0 { + pow *= sq; + } + sq *= sq; + } + return; + } + + n := len(substr); + switch { + case n == 0: + return len(s); + case n == 1: + return last_index_byte(s, substr[0]); + case n == len(s): + return substr == s ? 0 : -1; + case n > len(s): + return -1; + } + + hash, pow := hash_str_rabin_karp_reverse(substr); + last := len(s) - n; + h: u32; + for i := len(s)-1; i >= last; i -= 1 { + h = h*PRIME_RABIN_KARP + u32(s[i]); + } + if h == hash && s[last:] == substr { + return last; + } + + for i := last-1; i >= 0; i -= 1 { + h *= PRIME_RABIN_KARP; + h += u32(s[i]); + h -= pow * u32(s[i+n]); + if h == hash && s[i:i+n] == substr { return i; } } diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index eec7da45a..2c8148501 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -4,6 +4,7 @@ import "core:fmt" import "core:mem" import "core:os" import "core:reflect" +import "core:strings" import "intrinsics" when os.OS == "windows" { @@ -1189,7 +1190,15 @@ where_clauses :: proc() { } main :: proc() { - when true { + x := "foobarbaz"; + i : int; + i = strings.last_index(x, "foo"); fmt.println(i); + i = strings.last_index(x, "bar"); fmt.println(i); + i = strings.last_index(x, "baz"); fmt.println(i); + i = strings.last_index(x, "asd"); fmt.println(i); + i = strings.last_index(x, "a"); fmt.println(i); + i = strings.last_index(x, "ba"); fmt.println(i); + when false { general_stuff(); union_type(); parametric_polymorphism(); @@ -1212,3 +1221,4 @@ main :: proc() { where_clauses(); } } + diff --git a/src/build_settings.cpp b/src/build_settings.cpp index b4abf41a7..5d1c07a67 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -55,7 +55,7 @@ TargetEndianKind target_endians[TargetArch_COUNT] = { -String const ODIN_VERSION = str_lit("0.10.1"); +String const ODIN_VERSION = str_lit("0.10.2"); -- cgit v1.2.3