diff --git a/base/runtime/core.odin b/base/runtime/core.odin index cd7d35540..5ab8a7008 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -559,10 +559,14 @@ ALL_ODIN_OS_TYPES :: Odin_OS_Types{ Odin_Platform_Subtarget_Type :: enum int { Default, iOS, + Android, } */ Odin_Platform_Subtarget_Type :: type_of(ODIN_PLATFORM_SUBTARGET) +Odin_Platform_Subtarget_Types :: bit_set[Odin_Platform_Subtarget_Type] + + /* // Defined internally by the compiler Odin_Sanitizer_Flag :: enum u32 { diff --git a/core/odin/parser/file_tags.odin b/core/odin/parser/file_tags.odin index c5c6637c3..fff59ee1e 100644 --- a/core/odin/parser/file_tags.odin +++ b/core/odin/parser/file_tags.odin @@ -30,14 +30,27 @@ File_Tags :: struct { } @require_results -get_build_os_from_string :: proc(str: string) -> runtime.Odin_OS_Type { +get_build_os_from_string :: proc(str: string) -> (found_os: runtime.Odin_OS_Type, found_subtarget: runtime.Odin_Platform_Subtarget_Type) { + str_os, _, str_subtarget := strings.partition(str, ":") + fields := reflect.enum_fields_zipped(runtime.Odin_OS_Type) for os in fields { - if strings.equal_fold(os.name, str) { - return runtime.Odin_OS_Type(os.value) + if strings.equal_fold(os.name, str_os) { + found_os = runtime.Odin_OS_Type(os.value) + break } } - return .Unknown + if str_subtarget != "" { + fields := reflect.enum_fields_zipped(runtime.Odin_Platform_Subtarget_Type) + for subtarget in fields { + if strings.equal_fold(subtarget.name, str_subtarget) { + found_subtarget = runtime.Odin_Platform_Subtarget_Type(subtarget.value) + break + } + } + } + + return } @require_results get_build_arch_from_string :: proc(str: string) -> runtime.Odin_Arch_Type { @@ -187,7 +200,8 @@ parse_file_tags :: proc(file: ast.File, allocator := context.allocator) -> (tags if value == "ignore" { tags.ignore = true - } else if os := get_build_os_from_string(value); os != .Unknown { + } else if os, subtarget := get_build_os_from_string(value); os != .Unknown { + _ = subtarget // TODO(bill): figure out how to handle the subtarget logic if is_notted { os_negative += {os} } else { diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c2575e2d4..c941e0f68 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -847,13 +847,39 @@ gb_global NamedTargetMetrics *selected_target_metrics; gb_global Subtarget selected_subtarget; -gb_internal TargetOsKind get_target_os_from_string(String str) { +gb_internal TargetOsKind get_target_os_from_string(String str, Subtarget *subtarget_ = nullptr) { + String os_name = str; + String subtarget = {}; + auto part = string_partition(str, str_lit(":")); + if (part.match.len == 1) { + os_name = part.head; + subtarget = part.tail; + } + + TargetOsKind kind = TargetOs_Invalid; + for (isize i = 0; i < TargetOs_COUNT; i++) { - if (str_eq_ignore_case(target_os_names[i], str)) { - return cast(TargetOsKind)i; + if (str_eq_ignore_case(target_os_names[i], os_name)) { + kind = cast(TargetOsKind)i; + break; } } - return TargetOs_Invalid; + if (subtarget_) *subtarget_ = Subtarget_Default; + + if (subtarget.len != 0) { + if (str_eq_ignore_case(subtarget, "generic") || str_eq_ignore_case(subtarget, "default")) { + if (subtarget_) *subtarget_ = Subtarget_Default; + } else { + for (isize i = 1; i < Subtarget_COUNT; i++) { + if (str_eq_ignore_case(subtarget_strings[i], subtarget)) { + if (subtarget_) *subtarget_ = cast(Subtarget)i; + break; + } + } + } + } + + return kind; } gb_internal TargetArchKind get_target_arch_from_string(String str) { diff --git a/src/parser.cpp b/src/parser.cpp index f38f79607..a397585e8 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -6157,7 +6157,7 @@ gb_internal String build_tag_get_token(String s, String *out) { isize width = utf8_decode(&s[n], s.len-n, &rune); if (n == 0 && rune == '!') { - } else if (!rune_is_letter(rune) && !rune_is_digit(rune)) { + } else if (!rune_is_letter(rune) && !rune_is_digit(rune) && rune != ':') { isize k = gb_max(gb_max(n, width), 1); *out = substring(s, k, s.len); return substring(s, 0, k); @@ -6209,7 +6209,9 @@ gb_internal bool parse_build_tag(Token token_for_pos, String s) { continue; } - TargetOsKind os = get_target_os_from_string(p); + Subtarget subtarget = Subtarget_Default; + + TargetOsKind os = get_target_os_from_string(p, &subtarget); TargetArchKind arch = get_target_arch_from_string(p); num_tokens += 1; @@ -6223,11 +6225,13 @@ gb_internal bool parse_build_tag(Token token_for_pos, String s) { if (os != TargetOs_Invalid) { this_kind_os_seen = true; + bool same_subtarget = (subtarget == Subtarget_Default) || (subtarget == selected_subtarget); + GB_ASSERT(arch == TargetArch_Invalid); if (is_notted) { - this_kind_correct = this_kind_correct && (os != build_context.metrics.os); + this_kind_correct = this_kind_correct && (os != build_context.metrics.os || !same_subtarget); } else { - this_kind_correct = this_kind_correct && (os == build_context.metrics.os); + this_kind_correct = this_kind_correct && (os == build_context.metrics.os && same_subtarget); } } else if (arch != TargetArch_Invalid) { this_kind_arch_seen = true; diff --git a/src/string.cpp b/src/string.cpp index 88b679540..ae8d066b1 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -336,6 +336,83 @@ gb_internal Array split_lines_from_array(Array const &array, gbAlloc return lines; } +enum : u32 { PRIME_RABIN_KARP = 16777619u }; + +gb_internal u32 hash_str_rabin_karp(String const &s, u32 *pow_) { + u32 hash = 0; + u32 pow = 1; + for (isize i = 0; i < s.len; i++) { + hash = hash*PRIME_RABIN_KARP + cast(u32)s.text[i]; + } + u32 sq = PRIME_RABIN_KARP; + for (isize i = s.len; i > 0; i >>= 1) { + if ((i & 1) != 0) { + pow *= sq; + } + sq *= sq; + } + if (pow_) *pow_ = pow; + return hash; + +} + + +gb_internal isize string_index(String const &s, String const &substr) { + isize n = substr.len; + if (n == 0) { + return 0; + } else if (n == 1) { + return string_index_byte(s, substr[0]); + } else if (n == s.len) { + if (s == substr) { + return 0; + } + return -1; + } else if (n > s.len) { + return -1; + } + u32 pow = 1; + u32 hash = hash_str_rabin_karp(s, &pow); + u32 h = 0; + for (isize i = 0; i < n; i++) { + h = h*PRIME_RABIN_KARP + cast(u32)s.text[i]; + } + if (h == hash && substring(s, 0, n) == substr) { + return 0; + } + for (isize i = n; i < s.len; /**/) { + h *= PRIME_RABIN_KARP; + h += cast(u32)s.text[i]; + h -= pow * u32(s.text[i-n]); + i += 1; + if (h == hash && substring(s, i-n, i) == substr) { + return i - n; + } + } + return -1; +} + + +struct StringPartition { + String head; + String match; + String tail; +}; + +gb_internal StringPartition string_partition(String const &str, String const &sep) { + StringPartition res = {}; + isize i = string_index(str, sep); + if (i < 0) { + res.head = str; + return res; + } + + res.head = substring(str, 0, i); + res.match = substring(str, i, i+sep.len); + res.tail = substring(str, i+sep.len, str.len); + return res; +} + gb_internal bool string_contains_char(String const &s, u8 c) { isize i; for (i = 0; i < s.len; i++) {