aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/builtin.cpp55
-rw-r--r--src/builtin.h8
-rw-r--r--src/exec.cpp4
-rw-r--r--src/function.cpp16
-rw-r--r--src/function.h38
-rw-r--r--src/parse_execution.cpp4
6 files changed, 83 insertions, 42 deletions
diff --git a/src/builtin.cpp b/src/builtin.cpp
index e5261cb4..a79f898d 100644
--- a/src/builtin.cpp
+++ b/src/builtin.cpp
@@ -889,6 +889,7 @@ static int builtin_generic(parser_t &parser, io_streams_t &streams, wchar_t **ar
}
}
}
+
return STATUS_BUILTIN_ERROR;
}
@@ -919,7 +920,11 @@ static wcstring functions_def(const wcstring &name) {
out.append(esc_desc);
}
- if (!function_get_shadows(name)) {
+ if (function_get_shadow_builtin(name)) {
+ out.append(L" --shadow-builtin");
+ }
+
+ if (!function_get_shadow_scope(name)) {
out.append(L" --no-scope-shadowing");
}
@@ -1460,8 +1465,8 @@ static int builtin_pwd(parser_t &parser, io_streams_t &streams, wchar_t **argv)
}
/// Adds a function to the function set. It calls into function.cpp to perform any heavy lifting.
-int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args,
- const wcstring &contents, int definition_line_offset, wcstring *out_err) {
+int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args,
+ const wcstring &contents, int definition_line_offset, wcstring *out_err) {
wgetopter_t w;
assert(out_err != NULL);
@@ -1484,7 +1489,8 @@ int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list
wcstring_list_t named_arguments;
wcstring_list_t inherit_vars;
- bool shadows = true;
+ bool shadow_builtin = false;
+ bool shadow_scope = true;
wcstring_list_t wrap_targets;
@@ -1504,17 +1510,17 @@ int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list
{L"wraps", required_argument, 0, 'w'},
{L"help", no_argument, 0, 'h'},
{L"argument-names", no_argument, 0, 'a'},
+ {L"shadow-builtin", no_argument, 0, 'B'},
{L"no-scope-shadowing", no_argument, 0, 'S'},
{L"inherit-variable", required_argument, 0, 'V'},
{0, 0, 0, 0}};
- while (1 && (!res)) {
+ while (1 && !res) {
int opt_index = 0;
// The leading - here specifies RETURN_IN_ORDER.
- int opt = w.wgetopt_long(argc, argv, L"-d:s:j:p:v:e:w:haSV:", long_options, &opt_index);
+ int opt = w.wgetopt_long(argc, argv, L"-d:s:j:p:v:e:w:haBSV:", long_options, &opt_index);
if (opt == -1) break;
-
switch (opt) {
case 0: {
if (long_options[opt_index].flag != 0) break;
@@ -1536,7 +1542,6 @@ int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list
events.push_back(event_t::signal_event(sig));
break;
}
-
case 'v': {
if (wcsvarname(w.woptarg)) {
append_format(*out_err, _(L"%ls: Invalid variable name '%ls'"), argv[0],
@@ -1586,7 +1591,6 @@ int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list
e.type = EVENT_JOB_ID;
e.param1.job_id = job_id;
}
-
} else {
errno = 0;
pid = fish_wcstoi(w.woptarg, &end, 10);
@@ -1611,8 +1615,12 @@ int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list
name_is_first_positional = !positionals.empty();
break;
}
+ case 'B': {
+ shadow_builtin = true;
+ break;
+ }
case 'S': {
- shadows = 0;
+ shadow_scope = false;
break;
}
case 'w': {
@@ -1700,13 +1708,38 @@ int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list
}
if (!res) {
+ bool function_name_shadows_builtin = false;
+ wcstring_list_t builtin_names = builtin_get_names();
+ for (size_t i = 0; i < builtin_names.size(); i++) {
+ const wchar_t *el = builtin_names.at(i).c_str();
+ if (el == function_name) {
+ function_name_shadows_builtin = true;
+ break;
+ }
+ }
+ if (function_name_shadows_builtin && !shadow_builtin) {
+ append_format(
+ *out_err,
+ _(L"%ls: function name shadows a builtin so you must use '--shadow-builtin'"),
+ argv[0]);
+ res = STATUS_BUILTIN_ERROR;
+ } else if (!function_name_shadows_builtin && shadow_builtin) {
+ append_format(*out_err, _(L"%ls: function name does not shadow a builtin so you "
+ L"must not use '--shadow-builtin'"),
+ argv[0]);
+ res = STATUS_BUILTIN_ERROR;
+ }
+ }
+
+ if (!res) {
// Here we actually define the function!
function_data_t d;
d.name = function_name;
if (desc) d.description = desc;
d.events.swap(events);
- d.shadows = shadows;
+ d.shadow_builtin = shadow_builtin;
+ d.shadow_scope = shadow_scope;
d.named_arguments.swap(named_arguments);
d.inherit_vars.swap(inherit_vars);
diff --git a/src/builtin.h b/src/builtin.h
index 0d62babe..7648649d 100644
--- a/src/builtin.h
+++ b/src/builtin.h
@@ -93,10 +93,10 @@ class builtin_commandline_scoped_transient_t {
// Run the __fish_print_help function to obtain the help information for the specified command.
wcstring builtin_help_get(parser_t &parser, const wchar_t *cmd);
-// Defines a function, like builtin_function. Returns 0 on success. args should NOT contain
-// 'function' as the first argument.
-int define_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args,
- const wcstring &contents, int definition_line_offset, wcstring *out_err);
+// Defines a function. Returns 0 on success. args should NOT contain 'function' as the first
+// argument as the parser treats it as a keyword.
+int builtin_function(parser_t &parser, io_streams_t &streams, const wcstring_list_t &c_args,
+ const wcstring &contents, int definition_line_offset, wcstring *out_err);
// Print help for the specified builtin. If \c b is sb_err, also print the line information.
void builtin_print_help(parser_t &parser, io_streams_t &streams, const wchar_t *cmd,
diff --git a/src/exec.cpp b/src/exec.cpp
index 24a9af05..63f2cb77 100644
--- a/src/exec.cpp
+++ b/src/exec.cpp
@@ -636,7 +636,7 @@ void exec_job(parser_t &parser, job_t *j) {
wcstring def;
bool function_exists = function_get_definition(func_name, &def);
- bool shadows = function_get_shadows(func_name);
+ bool shadow_scope = function_get_shadow_scope(func_name);
const std::map<wcstring, env_var_t> inherit_vars =
function_get_inherit_vars(func_name);
@@ -646,7 +646,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, func_name, shadows);
+ function_block_t *newv = new function_block_t(p, func_name, shadow_scope);
parser.push_block(newv);
// Setting variables might trigger an event handler, hence we need to unblock
diff --git a/src/function.cpp b/src/function.cpp
index f717a16f..54559bee 100644
--- a/src/function.cpp
+++ b/src/function.cpp
@@ -141,7 +141,8 @@ function_info_t::function_info_t(const function_data_t &data, const wchar_t *fil
named_arguments(data.named_arguments),
inherit_vars(snapshot_vars(data.inherit_vars)),
is_autoload(autoload),
- shadows(data.shadows) {}
+ shadow_builtin(data.shadow_builtin),
+ shadow_scope(data.shadow_scope) {}
function_info_t::function_info_t(const function_info_t &data, const wchar_t *filename,
int def_offset, bool autoload)
@@ -152,7 +153,8 @@ function_info_t::function_info_t(const function_info_t &data, const wchar_t *fil
named_arguments(data.named_arguments),
inherit_vars(data.inherit_vars),
is_autoload(autoload),
- shadows(data.shadows) {}
+ shadow_builtin(data.shadow_builtin),
+ shadow_scope(data.shadow_scope) {}
void function_add(const function_data_t &data, const parser_t &parser, int definition_line_offset) {
ASSERT_IS_MAIN_THREAD();
@@ -255,10 +257,16 @@ std::map<wcstring, env_var_t> function_get_inherit_vars(const wcstring &name) {
return func ? func->inherit_vars : std::map<wcstring, env_var_t>();
}
-int function_get_shadows(const wcstring &name) {
+int function_get_shadow_builtin(const wcstring &name) {
scoped_lock lock(functions_lock);
const function_info_t *func = function_get(name);
- return func ? func->shadows : false;
+ return func ? func->shadow_builtin : false;
+}
+
+int function_get_shadow_scope(const wcstring &name) {
+ scoped_lock lock(functions_lock);
+ const function_info_t *func = function_get(name);
+ return func ? func->shadow_scope : false;
}
bool function_get_desc(const wcstring &name, wcstring *out_desc) {
diff --git a/src/function.h b/src/function.h
index 04829cbe..59b37051 100644
--- a/src/function.h
+++ b/src/function.h
@@ -31,44 +31,41 @@ struct function_data_t {
/// List of all variables that are inherited from the function definition scope. The variable
/// values are snapshotted when function_add() is called.
wcstring_list_t inherit_vars;
- /// Set to non-zero if invoking this function shadows the variables of the underlying function.
- int shadows;
+ /// Set to true if invoking this function shadows the variables of the underlying function.
+ bool shadow_scope;
+ /// Set to true if this function shadows a builtin.
+ bool shadow_builtin;
};
class function_info_t {
public:
- /// Constructs relevant information from the function_data.
- function_info_t(const function_data_t &data, const wchar_t *filename, int def_offset,
- bool autoload);
-
- /// Used by function_copy.
- function_info_t(const function_info_t &data, const wchar_t *filename, int def_offset,
- bool autoload);
-
/// Function definition.
const wcstring definition;
-
/// Function description. Only the description may be changed after the function is created.
wcstring description;
-
/// File where this function was defined (intern'd string).
const wchar_t *const definition_file;
-
/// Line where definition started.
const int definition_offset;
-
/// List of all named arguments for this function.
const wcstring_list_t named_arguments;
-
/// Mapping of all variables that were inherited from the function definition scope to their
/// values.
const std::map<wcstring, env_var_t> inherit_vars;
-
/// Flag for specifying that this function was automatically loaded.
const bool is_autoload;
-
+ /// Set to true if this function shadows a builtin.
+ const bool shadow_builtin;
/// Set to true if invoking this function shadows the variables of the underlying function.
- const bool shadows;
+ const bool shadow_scope;
+
+ /// Constructs relevant information from the function_data.
+ function_info_t(const function_data_t &data, const wchar_t *filename, int def_offset,
+ bool autoload);
+
+ /// Used by function_copy.
+ function_info_t(const function_info_t &data, const wchar_t *filename, int def_offset,
+ bool autoload);
};
/// Initialize function data.
@@ -133,8 +130,11 @@ std::map<wcstring, env_var_t> function_get_inherit_vars(const wcstring &name);
/// is successful.
bool function_copy(const wcstring &name, const wcstring &new_name);
+/// Returns whether this function shadows a builtin of the same name.
+int function_get_shadow_builtin(const wcstring &name);
+
/// Returns whether this function shadows variables of the underlying function.
-int function_get_shadows(const wcstring &name);
+int function_get_shadow_scope(const wcstring &name);
/// Prepares the environment for executing a function.
void function_prepare_environment(const wcstring &name, const wchar_t *const *argv,
diff --git a/src/parse_execution.cpp b/src/parse_execution.cpp
index cca0b8d9..7989597f 100644
--- a/src/parse_execution.cpp
+++ b/src/parse_execution.cpp
@@ -392,8 +392,8 @@ parse_execution_result_t parse_execution_context_t::run_function_statement(
int definition_line_offset = this->line_offset_of_character_at_offset(contents_start);
wcstring error_str;
io_streams_t streams;
- int err = define_function(*parser, streams, argument_list, contents_str,
- definition_line_offset, &error_str);
+ int err = builtin_function(*parser, streams, argument_list, contents_str,
+ definition_line_offset, &error_str);
proc_set_last_status(err);
if (!error_str.empty()) {