summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sysif.c61
-rw-r--r--txr.166
2 files changed, 108 insertions, 19 deletions
diff --git a/sysif.c b/sysif.c
index e51692db..6bf69715 100644
--- a/sysif.c
+++ b/sysif.c
@@ -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));
diff --git a/txr.1 b/txr.1
index d03525a5..6512ff9c 100644
--- a/txr.1
+++ b/txr.1
@@ -58879,10 +58879,28 @@ function.
.desc
The
.code env-hash
-function constructs and returns an
+function returns an
.code :equal-based
-hash. The hash is
-populated with the environment variables, represented as key-value pairs.
+hash whose keys and values are strings. The hash table is populated populated
+with the environment variables, represented as key-value character string
+pairs.
+
+The
+.code env-hash
+function allocates the hash table when it is first invoked; thereafter,
+it returns the same hash table.
+
+The hash table is updated by the functions
+.codn setenv ,
+.code unsetenv
+and
+.codn getenv .
+
+Note: calls to the underlying C library functions
+.code setenv
+and
+.codn getenv ,
+and other direct manipulations of the environment, will not update the hash table.
.coNP Functions @, getenv @ setenv and @ unsetenv
.synb
@@ -58989,6 +59007,43 @@ is restored by the
.code unwind-protect
cleanup form.
+These functions interact with the list returned by the
+.code env
+function and with the hash table returned by the
+.code env-hash
+function as follows.
+
+A previously returned list returned by
+.code env
+is not modified. The
+.code setenv
+and
+.code unsetenv
+functions may cause a subsequent call to
+.code env
+to return a different list. The
+.code getenv
+function has no effect on the list.
+
+The hash table previously returned by
+.code env-hash
+is modified by
+.code setenv
+in the manner consistent with its semantics. A new entry is created in the table,
+if required, and an existing entry is overwritten only if the
+.code overwrite-p
+flag is specified. Likewise, if
+.code setenv
+is invoked in a way that causes the environment variable to be deleted, it
+is removed from the hash also.
+The
+.code unsetenv
+function causes the variable to be removed from the hash table also.
+The
+.code getenv
+function accesses the underlying environment, and updates the hash
+table with the name-value pair which is retrieved.
+
.SS* Command Line Option Processing
\*(TL provides a support for recognizing, extracting and validating
@@ -75551,6 +75606,11 @@ of these version values, the described behaviors are provided if
is given an argument which is equal or lower. For instance
.code "-C 103"
selects the behaviors described below for version 105, but not those for 102.
+.IP 244
+Until \*(TX 244, the
+.code env-hash
+function returned a new hash table each time it was called. The behavior is
+restored if 244 or older compatibility is selected.
.IP 243
Two mistakes in the pseudo-random-number generator (PRNG) were discovered,
affecting \*(TX 243 and older. Using this compatibility value, or lower, will