소스 검색

Merge pull request #5332 from Kelimion/replace_environment_variables

Replace core:posix usage in core:os/os2
Jeroen van Rijn 2 달 전
부모
커밋
f03484e352
6개의 변경된 파일122개의 추가작업 그리고 33개의 파일을 삭제
  1. 2 24
      core/net/dns.odin
  2. 53 0
      core/os/os.odin
  3. 52 0
      core/os/os2/env.odin
  4. 1 9
      core/os/os2/user_posix.odin
  5. 5 0
      core/os/os_js.odin
  6. 9 0
      core/os/os_wasi.odin

+ 2 - 24
core/net/dns.odin

@@ -49,8 +49,8 @@ init_dns_configuration :: proc() {
 	/*
 		Resolve %ENVIRONMENT% placeholders in their paths.
 	*/
-	dns_configuration.resolv_conf, _ = replace_environment_path(dns_configuration.resolv_conf)
-	dns_configuration.hosts_file,  _ = replace_environment_path(dns_configuration.hosts_file)
+	dns_configuration.resolv_conf = os.replace_environment_placeholders(dns_configuration.resolv_conf)
+	dns_configuration.hosts_file  = os.replace_environment_placeholders(dns_configuration.hosts_file)
 }
 
 @(fini, private)
@@ -63,28 +63,6 @@ destroy_dns_configuration :: proc() {
 
 dns_configuration := DEFAULT_DNS_CONFIGURATION
 
-// Always allocates for consistency.
-replace_environment_path :: proc(path: string, allocator := context.allocator) -> (res: string, ok: bool) {
-	// Nothing to replace. Return a clone of the original.
-	if strings.count(path, "%") != 2 {
-		return strings.clone(path, allocator), true
-	}
-
-	left  := strings.index(path, "%") + 1
-	assert(left > 0 && left <= len(path)) // should be covered by there being two %
-
-	right := strings.index(path[left:], "%") + 1
-	assert(right > 0 && right <= len(path)) // should be covered by there being two %
-
-	env_key := path[left: right]
-	env_val := os.get_env(env_key, allocator)
-	defer delete(env_val)
-
-	res, _ = strings.replace(path, path[left - 1: right + 1], env_val, 1, allocator)
-	return res, true
-}
-
-
 /*
 	Resolves a hostname to exactly one IP4 and IP6 endpoint.
 	It's then up to you which one you use.

+ 53 - 0
core/os/os.odin

@@ -4,6 +4,7 @@ import "base:intrinsics"
 import "base:runtime"
 import "core:io"
 import "core:strconv"
+import "core:strings"
 import "core:unicode/utf8"
 
 
@@ -210,3 +211,55 @@ heap_free   :: runtime.heap_free
 processor_core_count :: proc() -> int {
 	return _processor_core_count()
 }
+
+// Always allocates for consistency.
+replace_environment_placeholders :: proc(path: string, allocator := context.allocator) -> (res: string) {
+	path := path
+
+	sb: strings.Builder
+	strings.builder_init_none(&sb, allocator)
+	for len(path) > 0 {
+		switch path[0] {
+		case '%': // Windows
+			when ODIN_OS == .Windows {
+				for r, i in path[1:] {
+					if r == '%' {
+						env_key := path[1:i+1]
+						env_val := get_env(env_key, context.temp_allocator)
+						strings.write_string(&sb, env_val)
+						path = path[i+1:] // % is part of key, so skip 1 character extra
+					}
+				}
+			} else {
+				strings.write_rune(&sb, rune(path[0]))
+			}
+
+		case '$': // Posix
+			when ODIN_OS != .Windows {
+				env_key := ""
+				dollar_loop: for r, i in path[1:] {
+					switch r {
+					case 'A'..='Z', 'a'..='z', '0'..='9', '_': // Part of key ident
+					case:
+						env_key = path[1:i+1]
+						break dollar_loop
+					}
+				}
+				if len(env_key) > 0 {
+					env_val := get_env(env_key, context.temp_allocator)
+					strings.write_string(&sb, env_val)
+					path = path[len(env_key):]
+				}
+
+			} else {
+				strings.write_rune(&sb, rune(path[0]))
+			}
+
+		case:
+			strings.write_rune(&sb, rune(path[0]))
+		}
+
+		path = path[1:]
+	}
+	return strings.to_string(sb)
+}

+ 52 - 0
core/os/os2/env.odin

@@ -1,6 +1,7 @@
 package os2
 
 import "base:runtime"
+import "core:strings"
 
 // get_env retrieves the value of the environment variable named by the key
 // It returns the value, which will be empty if the variable is not present
@@ -45,4 +46,55 @@ environ :: proc(allocator: runtime.Allocator) -> ([]string, Error) {
 	return _environ(allocator)
 }
 
+// Always allocates for consistency.
+replace_environment_placeholders :: proc(path: string, allocator: runtime.Allocator) -> (res: string) {
+	path := path
 
+	sb: strings.Builder
+	strings.builder_init_none(&sb, allocator)
+
+	for len(path) > 0 {
+		switch path[0] {
+		case '%': // Windows
+			when ODIN_OS == .Windows {
+				for r, i in path[1:] {
+					if r == '%' {
+						env_key := path[1:i+1]
+						env_val := get_env(env_key, context.temp_allocator)
+						strings.write_string(&sb, env_val)
+						path = path[i+1:] // % is part of key, so skip 1 character extra
+					}
+				}
+			} else {
+				strings.write_rune(&sb, rune(path[0]))
+			}
+
+		case '$': // Posix
+			when ODIN_OS != .Windows {
+				env_key := ""
+				dollar_loop: for r, i in path[1:] {
+					switch r {
+					case 'A'..='Z', 'a'..='z', '0'..='9', '_': // Part of key ident
+					case:
+						env_key = path[1:i+1]
+						break dollar_loop
+					}
+				}
+				if len(env_key) > 0 {
+					env_val := get_env(env_key, context.temp_allocator)
+					strings.write_string(&sb, env_val)
+					path = path[len(env_key):]
+				}
+
+			} else {
+				strings.write_rune(&sb, rune(path[0]))
+			}
+
+		case:
+			strings.write_rune(&sb, rune(path[0]))
+		}
+
+		path = path[1:]
+	}
+	return strings.to_string(sb)
+}

+ 1 - 9
core/os/os2/user_posix.odin

@@ -4,7 +4,6 @@ package os2
 import "base:runtime"
 import "core:encoding/ini"
 import "core:strings"
-import "core:sys/posix"
 
 _user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
 	#partial switch ODIN_OS {
@@ -169,14 +168,7 @@ _xdg_user_dirs_lookup :: proc(xdg_key: string, allocator: runtime.Allocator) ->
 
 	for k, v in ini.iterate(&it) {
 		if k == xdg_key {
-			we: posix.wordexp_t
-			defer posix.wordfree(&we)
-
-			if _err := posix.wordexp(strings.clone_to_cstring(v, temp_allocator), &we, nil); _err != nil || we.we_wordc != 1 {
-				return "", .Wordexp_Failed
-			}
-
-			return strings.clone_from_cstring(we.we_wordv[0], allocator)
+			return replace_environment_placeholders(v, allocator), nil
 		}
 	}
 	return

+ 5 - 0
core/os/os_js.odin

@@ -252,4 +252,9 @@ current_thread_id :: proc "contextless" () -> int {
 
 lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
 	return "", false
+}
+
+get_env :: proc(key: string, allocator := context.allocator) -> string {
+	value, _ := lookup_env(key, allocator)
+	return value
 }

+ 9 - 0
core/os/os_wasi.odin

@@ -239,3 +239,12 @@ exit :: proc "contextless" (code: int) -> ! {
 	runtime._cleanup_runtime_contextless()
 	wasi.proc_exit(wasi.exitcode_t(code))
 }
+
+lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
+	return "", false
+}
+
+get_env :: proc(key: string, allocator := context.allocator) -> string {
+	value, _ := lookup_env(key, allocator)
+	return value
+}