Rewrite env_exists() for better scope handling

env_exists() wasn't properly handling multiple scopes in some cases,
notably with readonly/electric variables. Rewrite it to operate in a
more straightforward fashion.
This commit is contained in:
Kevin Ballard 2014-07-12 01:15:52 -07:00
parent 383aaa236e
commit 76fdfe6890

74
env.cpp
View file

@ -1009,59 +1009,54 @@ bool env_exist(const wchar_t *key, int mode)
CHECK(key, false); CHECK(key, false);
/* const bool has_scope = mode & (ENV_LOCAL | ENV_GLOBAL | ENV_UNIVERSAL);
Read only variables all exist, and they are all global. A local const bool test_local = !has_scope || (mode & ENV_LOCAL);
version can not exist. const bool test_global = !has_scope || (mode & ENV_GLOBAL);
*/ const bool test_universal = !has_scope || (mode & ENV_UNIVERSAL);
if (!(mode & ENV_LOCAL) && !(mode & ENV_UNIVERSAL))
const bool test_exported = (mode & ENV_EXPORT) || !(mode & ENV_UNEXPORT);
const bool test_unexported = (mode & ENV_UNEXPORT) || !(mode & ENV_EXPORT);
if (is_electric(key))
{ {
if (is_read_only(key) || is_electric(key)) /*
Electric variables all exist, and they are all global. A local or
universal version can not exist. They are also never exported.
*/
if (test_global && test_unexported)
{ {
//Such variables are never exported
if (mode & ENV_EXPORT)
{
return false;
}
else if (mode & ENV_UNEXPORT)
{
return true;
}
return true; return true;
} }
return false;
} }
if (!(mode & ENV_UNIVERSAL)) if (test_local || test_global)
{ {
env = (mode & ENV_GLOBAL)?global_env:top; env = test_local ? top : global_env;
while (env != 0) while (env)
{ {
var_table_t::iterator result = env->env.find(key); var_table_t::iterator result = env->env.find(key);
if (result != env->env.end()) if (result != env->env.end())
{ {
const var_entry_t &res = result->second; const var_entry_t &res = result->second;
return res.exportv ? test_exported : test_unexported;
if (mode & ENV_EXPORT)
{
return res.exportv;
}
else if (mode & ENV_UNEXPORT)
{
return ! res.exportv;
}
return true;
} }
if (mode & ENV_LOCAL) if (has_scope)
break; {
if (!test_global || env == global_env) break;
env = env->next_scope_to_search(); env = global_env;
}
else
{
env = env->next_scope_to_search();
}
} }
} }
if (!(mode & ENV_LOCAL) && !(mode & ENV_GLOBAL)) if (test_universal)
{ {
if (! get_proc_had_barrier()) if (! get_proc_had_barrier())
{ {
@ -1071,16 +1066,7 @@ bool env_exist(const wchar_t *key, int mode)
if (uvars() && ! uvars()->get(key).missing()) if (uvars() && ! uvars()->get(key).missing())
{ {
if (mode & ENV_EXPORT) return uvars()->get_export(key) ? test_exported : test_unexported;
{
return uvars()->get_export(key);
}
else if (mode & ENV_UNEXPORT)
{
return ! uvars()->get_export(key);
}
return 1;
} }
} }