Factor function environment preparation into its own function

This commit is contained in:
ridiculousfish 2015-08-15 13:37:17 -07:00
parent 60798798ef
commit 93d57bd73a
8 changed files with 68 additions and 56 deletions

View file

@ -3446,7 +3446,7 @@ static int builtin_source(parser_t &parser, wchar_t ** argv)
parser.push_block(new source_block_t(fn_intern));
reader_push_current_filename(fn_intern);
parse_util_set_argv((argc>2)?(argv+2):(argv+1), wcstring_list_t());
env_set_argv((argc>2)?(argv+2):(argv+1));
res = reader_read(fd, real_io ? *real_io : io_chain_t());

View file

@ -1354,6 +1354,30 @@ const char * const *env_export_arr(bool recalc)
return export_array.get();
}
void env_set_argv(const wchar_t * const * argv)
{
if (*argv)
{
const wchar_t * const *arg;
wcstring sb;
for (arg=argv; *arg; arg++)
{
if (arg != argv)
{
sb.append(ARRAY_SEP_STR);
}
sb.append(*arg);
}
env_set(L"argv", sb.c_str(), ENV_LOCAL);
}
else
{
env_set(L"argv", 0, ENV_LOCAL);
}
}
env_vars_snapshot_t::env_vars_snapshot_t(const wchar_t * const *keys)
{
ASSERT_IS_MAIN_THREAD();

View file

@ -209,6 +209,9 @@ void env_universal_barrier();
/** Returns an array containing all exported variables in a format suitable for execv. */
const char * const * env_export_arr(bool recalc);
/** Sets up argv as the given null terminated array of strings */
void env_set_argv(const wchar_t * const * argv);
/**
Returns all variable names.
*/

View file

@ -774,12 +774,12 @@ void exec_job(parser_t &parser, job_t *j)
*/
signal_unblock();
const wcstring func_name = p->argv0();
wcstring def;
bool function_exists = function_get_definition(p->argv0(), &def);
bool function_exists = function_get_definition(func_name, &def);
wcstring_list_t named_arguments = function_get_named_arguments(p->argv0());
bool shadows = function_get_shadows(p->argv0());
std::map<wcstring,env_var_t> inherit_vars = function_get_inherit_vars(p->argv0());
bool shadows = function_get_shadows(func_name);
const std::map<wcstring,env_var_t> inherit_vars = function_get_inherit_vars(func_name);
signal_block();
@ -788,7 +788,7 @@ void exec_job(parser_t &parser, job_t *j)
debug(0, _(L"Unknown function '%ls'"), p->argv0());
break;
}
function_block_t *newv = new function_block_t(p, p->argv0(), shadows);
function_block_t *newv = new function_block_t(p, func_name, shadows);
parser.push_block(newv);
/*
@ -797,14 +797,10 @@ void exec_job(parser_t &parser, job_t *j)
signals.
*/
signal_unblock();
parse_util_set_argv(p->get_argv()+1, named_arguments);
for (std::map<wcstring,env_var_t>::const_iterator it = inherit_vars.begin(), end = inherit_vars.end(); it != end; ++it)
{
env_set(it->first, it->second.missing() ? NULL : it->second.c_str(), ENV_LOCAL | ENV_USER);
}
function_prepare_environment(func_name, p->get_argv()+1, inherit_vars);
signal_block();
parser.forbid_function(p->argv0());
parser.forbid_function(func_name);
if (p->next)
{

View file

@ -387,3 +387,32 @@ int function_get_definition_offset(const wcstring &name)
const function_info_t *func = function_get(name);
return func ? func->definition_offset : -1;
}
void function_prepare_environment(const wcstring &name, const wchar_t * const * argv, const std::map<wcstring, env_var_t> &inherited_vars)
{
/* Three components of the environment:
1. argv
2. named arguments
3. inherited variables
*/
env_set_argv(argv);
const wcstring_list_t named_arguments = function_get_named_arguments(name);
if (! named_arguments.empty())
{
const wchar_t * const *arg;
size_t i;
for (i=0, arg=argv; i < named_arguments.size(); i++)
{
env_set(named_arguments.at(i).c_str(), *arg, ENV_LOCAL | ENV_USER);
if (*arg)
arg++;
}
}
for (std::map<wcstring,env_var_t>::const_iterator it = inherited_vars.begin(), end = inherited_vars.end(); it != end; ++it)
{
env_set(it->first, it->second.missing() ? NULL : it->second.c_str(), ENV_LOCAL | ENV_USER);
}
}

View file

@ -179,10 +179,13 @@ std::map<wcstring,env_var_t> function_get_inherit_vars(const wcstring &name);
*/
bool function_copy(const wcstring &name, const wcstring &new_name);
/**
Returns whether this function shadows variables of the underlying function
*/
int function_get_shadows(const wcstring &name);
/** Prepares the environment for executing a function.
*/
void function_prepare_environment(const wcstring &name, const wchar_t * const * argv, const std::map<wcstring, env_var_t> &inherited_vars);
#endif

View file

@ -561,43 +561,6 @@ void parse_util_token_extent(const wchar_t *buff,
}
void parse_util_set_argv(const wchar_t * const *argv, const wcstring_list_t &named_arguments)
{
if (*argv)
{
const wchar_t * const *arg;
wcstring sb;
for (arg=argv; *arg; arg++)
{
if (arg != argv)
{
sb.append(ARRAY_SEP_STR);
}
sb.append(*arg);
}
env_set(L"argv", sb.c_str(), ENV_LOCAL);
}
else
{
env_set(L"argv", 0, ENV_LOCAL);
}
if (! named_arguments.empty())
{
const wchar_t * const *arg;
size_t i;
for (i=0, arg=argv; i < named_arguments.size(); i++)
{
env_set(named_arguments.at(i).c_str(), *arg, ENV_LOCAL | ENV_USER);
if (*arg)
arg++;
}
}
}
wchar_t *parse_util_unescape_wildcards(const wchar_t *str)
{
wchar_t *in, *out;

View file

@ -137,12 +137,6 @@ size_t parse_util_get_offset_from_line(const wcstring &str, int line);
*/
size_t parse_util_get_offset(const wcstring &str, int line, long line_offset);
/**
Set the argv environment variable to the specified null-terminated
array of strings.
*/
void parse_util_set_argv(const wchar_t * const *argv, const wcstring_list_t &named_arguments);
/**
Make a duplicate of the specified string, unescape wildcard
characters but not performing any other character transformation.