diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-10-16 07:12:38 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-10-16 07:12:38 -0700 |
commit | ac6a452df1c5c5c9d2fc3118278fddc913df1faa (patch) | |
tree | 94be782a03773d9722895ed4833b08a3f336d78f /sysif.c | |
parent | 11801dbdc034a43cdb5865ed6e1b55c4dd761e22 (diff) | |
download | txr-ac6a452df1c5c5c9d2fc3118278fddc913df1faa.tar.gz txr-ac6a452df1c5c5c9d2fc3118278fddc913df1faa.tar.bz2 txr-ac6a452df1c5c5c9d2fc3118278fddc913df1faa.zip |
env-hash: now persistent and synced with setenv.
* sysif.c (env_hash): Function renamed to get_env_hash and a
static variable named env_hash introduced.
Function returns a previously allocated hash table, if
it exists, except in compat mode.
(getenv_wrap): Stash the result into the hash also.
(setenv_wrap): Keep the hash up-to-date with the action of
setenv.
(unsetenv_wrap): Also delete from the hash.
(sysif_init): Protect the env_hash variable from gc.
* txr.1: Documented, with compat notes.
Diffstat (limited to 'sysif.c')
-rw-r--r-- | sysif.c | 61 |
1 files changed, 45 insertions, 16 deletions
@@ -148,7 +148,7 @@ static val at_exit_list; static val dirent_st; -static val env_list; +static val env_list, env_hash; static val errno_wrap(val newval) { @@ -322,20 +322,27 @@ val env(void) } } -static val env_hash(void) +static val get_env_hash(void) { - val env_strings = env(); - val hash = make_hash(nil, nil, t); + if (env_hash) { + return env_hash; + } else { + val env_strings = env(); + val hash = make_hash(nil, nil, t); + + for (; env_strings; env_strings = cdr(env_strings)) { + val estr = car(env_strings); + val eqpos = break_str(estr, lit("=")); + val key = sub(estr, 0, eqpos); + val val = sub(estr, succ(eqpos), t); + sethash(hash, key, val); + } - for (; env_strings; env_strings = cdr(env_strings)) { - val estr = car(env_strings); - val eqpos = break_str(estr, lit("=")); - val key = sub(estr, 0, eqpos); - val val = sub(estr, succ(eqpos), t); - sethash(hash, key, val); - } + if (!opt_compat || opt_compat > 244) + env_hash = hash; - return hash; + return hash; + } } val errno_to_file_error(int err) @@ -1386,20 +1393,39 @@ val getenv_wrap(val name) char *lookup = getenv(nameu8); val result = lookup ? string_utf8(lookup) : nil; free(nameu8); + if (env_hash) + sethash(env_hash, name, result); return result; } static val setenv_wrap(val name, val value, val overwrite) { + val self = lit("setenv"); const wchar_t *wname = c_str(name); const wchar_t *wvalu = value ? c_str(value) : 0; int ovw = default_arg_strict(overwrite, t) != nil; char *nameu8 = utf8_dup_to(wname); char *valu8 = wvalu ? utf8_dup_to(wvalu) : 0; - if (valu8) + if (valu8) { setenv(nameu8, valu8, ovw); - else if (ovw) + env_list = nil; + + if (env_hash) { + if (ovw) { + sethash(env_hash, name, value); + } else { + val new_p; + val cell = gethash_c(self, env_hash, name, mkcloc(new_p)); + if (new_p) + us_rplacd(cell, value); + } + } + } else if (ovw) { unsetenv(nameu8); + env_list = nil; + if (env_hash) + remhash(env_hash, name); + } free(valu8); free(nameu8); return value; @@ -1410,6 +1436,9 @@ static val unsetenv_wrap(val name) char *nameu8 = utf8_dup_to(c_str(name)); unsetenv(nameu8); free(nameu8); + env_list = nil; + if (env_hash) + remhash(env_hash, name); return name; } @@ -2389,7 +2418,7 @@ static val dirstat(val dirent, val dir_path, val stat_opt) void sysif_init(void) { - protect(&at_exit_list, dirent_st, &env_list, convert(val *, 0)); + protect(&at_exit_list, dirent_st, &env_list, &env_hash, convert(val *, 0)); atexit(at_exit_handler); @@ -2585,7 +2614,7 @@ void sysif_init(void) #endif reg_fun(intern(lit("env"), user_package), func_n0(env)); - reg_fun(intern(lit("env-hash"), user_package), func_n0(env_hash)); + reg_fun(intern(lit("env-hash"), user_package), func_n0(get_env_hash)); #if HAVE_DAEMON reg_fun(intern(lit("daemon"), user_package), func_n2(daemon_wrap)); |