From fa68c4e324257115c9334f980bf1fa5d11a91e13 Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Sat, 9 May 2026 13:02:44 +0200 Subject: [PATCH] Implemented access to environment variables --- lib/cli/env_unix.q | 28 ++++++++++++++++++++++++++++ lib/cli/env_windows.q | 36 ++++++++++++++++++++++++++++++++++++ lib/cli/init_linux_arm.q | 1 + lib/cli/init_linux_x86.q | 1 + lib/cli/init_mac_arm.q | 3 ++- lib/cli/init_mac_x86.q | 3 ++- lib/cli/init_windows.q | 9 +++++++++ lib/strings/cut.q | 6 +++--- tests/cli-env.q | 7 +++++++ tests/strings-cut.q | 8 ++++---- tests/tests_test.go | 3 ++- 11 files changed, 95 insertions(+), 10 deletions(-) create mode 100644 lib/cli/env_unix.q create mode 100644 lib/cli/env_windows.q create mode 100644 lib/cli/init_windows.q create mode 100644 tests/cli-env.q diff --git a/lib/cli/env_unix.q b/lib/cli/env_unix.q new file mode 100644 index 0000000..0faa946 --- /dev/null +++ b/lib/cli/env_unix.q @@ -0,0 +1,28 @@ +import c +import strings + +env(name string) -> (value string, err error) { + cur := envp + + loop { + ptr := [cur] + + if ptr == 0 { + return "", -1 + } + + current := string{ptr: ptr, len: c.length(ptr)} + key, value, err := strings.cut(current, "=") + assert err == 0 + + if strings.equal(key, name) { + return value, 0 + } + + cur = cur + 8 + } +} + +global { + envp **byte +} \ No newline at end of file diff --git a/lib/cli/env_windows.q b/lib/cli/env_windows.q new file mode 100644 index 0000000..8d92e5a --- /dev/null +++ b/lib/cli/env_windows.q @@ -0,0 +1,36 @@ +import c +import strings + +env(name string) -> (value string, err error) { + ptr := envp + + loop { + if [ptr] == 0 { + return "", -1 + } + + current := string{ptr: ptr, len: c.length(ptr)} + value, err := extract(current, name) + + if err == 0 { + return value, 0 + } + + ptr = ptr + current.len + 1 + } +} + +extract(current string, name string) -> (string, error) { + key, value, err := strings.cut(current, "=") + assert err == 0 + + if strings.equal(key, name) { + return value, 0 + } + + return "", -1 +} + +global { + envp *byte +} \ No newline at end of file diff --git a/lib/cli/init_linux_arm.q b/lib/cli/init_linux_arm.q index a7dc01c..e9dacf8 100644 --- a/lib/cli/init_linux_arm.q +++ b/lib/cli/init_linux_arm.q @@ -2,4 +2,5 @@ init() { stack := asm.sp as *uint argc = [stack] argv = stack + 8 + envp = argv + argc * 8 + 8 } \ No newline at end of file diff --git a/lib/cli/init_linux_x86.q b/lib/cli/init_linux_x86.q index 11362bc..51ac13b 100644 --- a/lib/cli/init_linux_x86.q +++ b/lib/cli/init_linux_x86.q @@ -2,4 +2,5 @@ init() { stack := asm.sp + 8 as *uint argc = [stack] argv = stack + 8 + envp = argv + argc * 8 + 8 } \ No newline at end of file diff --git a/lib/cli/init_mac_arm.q b/lib/cli/init_mac_arm.q index 9e5ee16..717cdcc 100644 --- a/lib/cli/init_mac_arm.q +++ b/lib/cli/init_mac_arm.q @@ -1,4 +1,5 @@ -init(r0 uint, r1 **byte, _r2 **byte) { +init(r0 uint, r1 **byte, r2 **byte) { argc = r0 argv = r1 + envp = r2 } \ No newline at end of file diff --git a/lib/cli/init_mac_x86.q b/lib/cli/init_mac_x86.q index ea39ea4..16ce607 100644 --- a/lib/cli/init_mac_x86.q +++ b/lib/cli/init_mac_x86.q @@ -1,4 +1,5 @@ -init(_r0 any, r7 uint, r6 **byte, _r2 **byte) { +init(_r0 any, r7 uint, r6 **byte, r2 **byte) { argc = r7 argv = r6 + envp = r2 } \ No newline at end of file diff --git a/lib/cli/init_windows.q b/lib/cli/init_windows.q new file mode 100644 index 0000000..e2fecfc --- /dev/null +++ b/lib/cli/init_windows.q @@ -0,0 +1,9 @@ +init() { + envp = kernel32.GetEnvironmentStrings() +} + +extern { + kernel32 { + GetEnvironmentStrings() -> *byte + } +} \ No newline at end of file diff --git a/lib/strings/cut.q b/lib/strings/cut.q index 62dd67a..8da5084 100644 --- a/lib/strings/cut.q +++ b/lib/strings/cut.q @@ -1,9 +1,9 @@ -cut(s string, separator string) -> (string, string) { +cut(s string, separator string) -> (before string, after string, err error) { pos, err := index(s, separator) if err != 0 { - return s, "" + return "", "", -1 } - return s[..pos], s[pos+separator.len..] + return s[..pos], s[pos+separator.len..], 0 } \ No newline at end of file diff --git a/tests/cli-env.q b/tests/cli-env.q new file mode 100644 index 0000000..cd0545e --- /dev/null +++ b/tests/cli-env.q @@ -0,0 +1,7 @@ +import cli + +main() { + path, err := cli.env("PATH") + assert err == 0 + assert path.len > 0 +} \ No newline at end of file diff --git a/tests/strings-cut.q b/tests/strings-cut.q index 7786ba1..0855c89 100644 --- a/tests/strings-cut.q +++ b/tests/strings-cut.q @@ -1,11 +1,11 @@ import strings main() { - hello, world := strings.cut("Hello World", " ") + hello, world, err := strings.cut("Hello World", " ") + assert err == 0 assert strings.equal(hello, "Hello") assert strings.equal(world, "World") - sekai, empty := strings.cut("世界", ":") - assert strings.equal(sekai, "世界") - assert strings.equal(empty, "") + _, _, err := strings.cut("世界", ":") + assert err != 0 } \ No newline at end of file diff --git a/tests/tests_test.go b/tests/tests_test.go index e30de66..b883bbd 100644 --- a/tests/tests_test.go +++ b/tests/tests_test.go @@ -132,6 +132,7 @@ var tests = []run{ {"cli-args", []string{"Hello"}, "", "Hello\n", 0}, {"cli-args", []string{"Hello", "World"}, "", "Hello\nWorld\n", 0}, {"cli-args", []string{"Hello", "世界"}, "", "Hello\n世界\n", 0}, + {"cli-env", nil, "", "", 0}, } func TestTests(t *testing.T) { @@ -140,4 +141,4 @@ func TestTests(t *testing.T) { build.Lint(false) test.Run(t, build) } -} +} \ No newline at end of file -- 2.51.2