summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2025-09-28 09:35:48 +0800
committerruki <[email protected]>2025-09-28 09:45:11 +0800
commit0e4844720e073b6d7fc3e8cad093a040155173ce (patch)
tree0361e1f2b17cb9fc19d978385a882e05630fc738
parentdd07af97f1b28ed18a9cd4a66dfd574f8fc795fb (diff)
improve os.getenvs
-rw-r--r--core/src/xmake/os/getenvs.c92
-rw-r--r--xmake/core/base/os.lua23
2 files changed, 75 insertions, 40 deletions
diff --git a/core/src/xmake/os/getenvs.c b/core/src/xmake/os/getenvs.c
index 5b8f0ba41..2ab29e614 100644
--- a/core/src/xmake/os/getenvs.c
+++ b/core/src/xmake/os/getenvs.c
@@ -56,6 +56,78 @@ extern tb_char_t** environ;
/* //////////////////////////////////////////////////////////////////////////////////////
* implementation
*/
+static tb_void_t xm_os_getenvs_trim(tb_char_t** sstr, tb_char_t** estr)
+{
+ // check
+ tb_assert(sstr && estr && *sstr && *estr);
+
+ tb_char_t* p = *sstr;
+ tb_char_t* e = *estr;
+
+ // trim left
+ while (p < e && tb_isspace(*p))
+ p++;
+
+ // trim right
+ while (e > p && tb_isspace(*(e - 1)))
+ e--;
+
+ // save trimmed string
+ *sstr = p;
+ *estr = e;
+}
+
+static tb_void_t xm_os_getenvs_process_line(lua_State* lua, tb_char_t const* line)
+{
+ // check
+ tb_assert_and_check_return(lua && line);
+
+ tb_int_t n = tb_strlen(line);
+ tb_check_return(n > 0);
+
+ // find '=' separator
+ tb_char_t const* p = tb_strchr(line, '=');
+ tb_check_return(p);
+
+ // get key and value parts
+ tb_char_t const* key_start = line;
+ tb_char_t const* key_end = p;
+ tb_char_t const* value_start = p + 1;
+ tb_char_t const* value_end = line + n;
+
+ // trim key
+ xm_os_getenvs_trim((tb_char_t**)&key_start, (tb_char_t**)&key_end);
+ if (key_start >= key_end) return;
+
+ // trim value
+ xm_os_getenvs_trim((tb_char_t**)&value_start, (tb_char_t**)&value_end);
+
+ // get key and value lengths
+ tb_size_t key_len = key_end - key_start;
+ tb_size_t value_len = value_end > value_start ? value_end - value_start : 0;
+
+ // handle Windows-specific PATH conversion
+ tb_char_t const* final_key_start = key_start;
+ tb_size_t final_key_len = key_len;
+#if defined(TB_CONFIG_OS_WINDOWS) && !defined(TB_COMPILER_LIKE_UNIX)
+ if (key_len == 4 && tb_strnicmp(key_start, "path", 4) == 0)
+ {
+ // use "PATH" instead of "path"
+ static tb_char_t const PATH_UPPER[] = "PATH";
+ final_key_start = PATH_UPPER;
+ final_key_len = 4;
+ }
+#endif
+
+ // set key-value pair in Lua table using pushlstring to avoid length limits
+ lua_pushlstring(lua, final_key_start, final_key_len);
+ if (value_len > 0)
+ lua_pushlstring(lua, value_start, value_len);
+ else
+ lua_pushliteral(lua, "");
+ lua_rawset(lua, -3);
+}
+
tb_int_t xm_os_getenvs(lua_State* lua)
{
// check
@@ -68,7 +140,6 @@ tb_int_t xm_os_getenvs(lua_State* lua)
tb_wchar_t const* p = (tb_wchar_t const*)GetEnvironmentStringsW();
if (p)
{
- tb_int_t i = 1;
tb_char_t* data = tb_null;
tb_size_t maxn = 0;
tb_char_t line[TB_PATH_MAXN];
@@ -79,10 +150,7 @@ tb_int_t xm_os_getenvs(lua_State* lua)
if (n + 1 < tb_arrayn(line))
{
if (tb_wtoa(line, p, tb_arrayn(line)) >= 0)
- {
- lua_pushstring(lua, line);
- lua_rawseti(lua, -2, i++);
- }
+ xm_os_getenvs_process_line(lua, line);
}
else
{
@@ -99,10 +167,7 @@ tb_int_t xm_os_getenvs(lua_State* lua)
tb_assert_and_check_break(data);
if (tb_wtoa(data, p, maxn) >= 0)
- {
- lua_pushstring(lua, data);
- lua_rawseti(lua, -2, i++);
- }
+ xm_os_getenvs_process_line(lua, data);
}
p += n + 1;
}
@@ -113,16 +178,9 @@ tb_int_t xm_os_getenvs(lua_State* lua)
tb_char_t const** p = (tb_char_t const**)environ;
if (p)
{
- tb_int_t i = 1;
- tb_size_t n = 0;
while (*p)
{
- n = tb_strlen(*p);
- if (n)
- {
- lua_pushstring(lua, *p);
- lua_rawseti(lua, -2, i++);
- }
+ xm_os_getenvs_process_line(lua, *p);
p++;
}
}
diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua
index 57046813e..41fe07d22 100644
--- a/xmake/core/base/os.lua
+++ b/xmake/core/base/os.lua
@@ -42,7 +42,6 @@ os._tmpdir = os._tmpdir or os.tmpdir
os._curdir = os._curdir or os.curdir
os._fscase = os._fscase or os.fscase
os._setenv = os._setenv or os.setenv
-os._getenvs = os._getenvs or os.getenvs
os._cpuinfo = os._cpuinfo or os.cpuinfo
os._meminfo = os._meminfo or os.meminfo
os._readlink = os._readlink or os.readlink
@@ -1300,28 +1299,6 @@ function os.term()
return require("base/tty").term()
end
--- get all current environment variables
--- e.g. envs["PATH"] = "/xxx:/yyy/foo"
-function os.getenvs()
- local envs = {}
- for _, line in ipairs(os._getenvs()) do
- local p = line:find('=', 1, true)
- if p then
- local key = line:sub(1, p - 1):trim()
- -- only translate Path to PATH on windows
- -- @see https://github.com/xmake-io/xmake/issues/3752
- if os.host() == "windows" and key:lower() == "path" then
- key = key:upper()
- end
- local values = line:sub(p + 1):trim()
- if #key > 0 then
- envs[key] = values
- end
- end
- end
- return envs
-end
-
-- set all current environment variables
-- e.g. envs["PATH"] = "/xxx:/yyy/foo"
function os.setenvs(envs)