Skip to content
Browse files

Update style and formatting to conform to fish style guide.

  • Loading branch information...
1 parent e2fe873 commit 53814983ff5404d0d2a53069ed2bc951a85ea0ee @ridiculousfish ridiculousfish committed Jan 15, 2014
Showing with 703 additions and 683 deletions.
  1. +20 −20 builtin.cpp
  2. +1 −1 builtin_set.cpp
  3. +3 −3 common.cpp
  4. +29 −29 complete.cpp
  5. +4 −4 env_universal.cpp
  6. +2 −2 event.cpp
  7. +8 −8 exec.cpp
  8. +2 −2 expand.cpp
  9. +99 −93 fish_tests.cpp
  10. +1 −1 function.cpp
  11. +60 −60 highlight.cpp
  12. +4 −4 highlight.h
  13. +1 −1 history.h
  14. +12 −11 parse_constants.h
  15. +197 −197 parse_execution.cpp
  16. +21 −21 parse_execution.h
  17. +4 −4 parse_productions.cpp
  18. +79 −79 parse_tree.cpp
  19. +26 −26 parse_tree.h
  20. +41 −41 parse_util.cpp
  21. +5 −5 parse_util.h
  22. +24 −24 parser.cpp
  23. +12 −12 parser.h
  24. +1 −1 proc.cpp
  25. +3 −3 proc.h
  26. +11 −11 reader.cpp
  27. +2 −1 screen.cpp
  28. +31 −19 tokenizer.cpp
View
40 builtin.cpp
@@ -1038,14 +1038,14 @@ static int builtin_emit(parser_t &parser, wchar_t **argv)
static int builtin_generic(parser_t &parser, wchar_t **argv)
{
int argc=builtin_count_args(argv);
-
+
/* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
if (argc == 1)
{
builtin_print_help(parser, argv[0], stdout_buffer);
return STATUS_BUILTIN_ERROR;
}
-
+
woptind=0;
static const struct woption
@@ -1754,16 +1754,16 @@ static int builtin_pwd(parser_t &parser, wchar_t **argv)
int define_function(parser_t &parser, const wcstring_list_t &c_args, const wcstring &contents, wcstring *out_err)
{
assert(out_err != NULL);
-
+
/* wgetopt expects 'function' as the first argument. Make a new wcstring_list with that property. */
wcstring_list_t args;
args.push_back(L"function");
args.insert(args.end(), c_args.begin(), c_args.end());
-
+
/* Hackish const_cast matches the one in builtin_run */
const null_terminated_array_t<wchar_t> argv_array(args);
wchar_t **argv = const_cast<wchar_t **>(argv_array.get());
-
+
int argc = builtin_count_args(argv);
int res=STATUS_BUILTIN_OK;
wchar_t *desc=0;
@@ -1806,9 +1806,9 @@ int define_function(parser_t &parser, const wcstring_list_t &c_args, const wcstr
case 0:
if (long_options[opt_index].flag != 0)
break;
-
-
-
+
+
+
append_format(*out_err,
BUILTIN_ERR_UNKNOWN,
argv[0],
@@ -1876,15 +1876,15 @@ int define_function(parser_t &parser, const wcstring_list_t &c_args, const wcstr
if (is_subshell)
{
size_t block_idx = 0;
-
+
/* Find the outermost substitution block */
for (block_idx = 0; ; block_idx++)
{
const block_t *b = parser.block_at_index(block_idx);
if (b == NULL || b->type() == SUBST)
break;
}
-
+
/* Go one step beyond that, to get to the caller */
const block_t *caller_block = parser.block_at_index(block_idx + 1);
if (caller_block != NULL && caller_block->job != NULL)
@@ -2046,9 +2046,9 @@ int define_function(parser_t &parser, const wcstring_list_t &c_args, const wcstr
event_t &e = d.events.at(i);
e.function_name = d.name;
}
-
+
d.definition = contents.c_str();
-
+
// TODO: fix def_offset inside function_add
function_add(d, parser);
}
@@ -2068,7 +2068,7 @@ static int builtin_function(parser_t &parser, wchar_t **argv)
builtin_print_help(parser, argv[0], stdout_buffer);
return STATUS_BUILTIN_OK;
}
-
+
int argc = builtin_count_args(argv);
int res=STATUS_BUILTIN_OK;
wchar_t *desc=0;
@@ -2181,15 +2181,15 @@ static int builtin_function(parser_t &parser, wchar_t **argv)
if (is_subshell)
{
size_t block_idx = 0;
-
+
/* Find the outermost substitution block */
for (block_idx = 0; ; block_idx++)
{
const block_t *b = parser.block_at_index(block_idx);
if (b == NULL || b->type() == SUBST)
break;
}
-
+
/* Go one step beyond that, to get to the caller */
const block_t *caller_block = parser.block_at_index(block_idx + 1);
if (caller_block != NULL && caller_block->job != NULL)
@@ -3965,7 +3965,7 @@ static int builtin_break_continue(parser_t &parser, wchar_t **argv)
{
parser.block_at_index(block_idx)->skip = true;
}
-
+
/* Skip the loop itself */
block_t *loop_block = parser.block_at_index(loop_idx);
loop_block->skip = true;
@@ -4043,7 +4043,7 @@ static int builtin_return(parser_t &parser, wchar_t **argv)
builtin_print_help(parser, argv[0], stderr_buffer);
return STATUS_BUILTIN_ERROR;
}
-
+
/* Skip everything up to (and then including) the function block */
for (size_t i=0; i < function_block_idx; i++)
{
@@ -4063,8 +4063,8 @@ static int builtin_switch(parser_t &parser, wchar_t **argv)
{
int res=STATUS_BUILTIN_OK;
int argc = builtin_count_args(argv);
-
- /* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
+
+ /* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
if (argc == 1)
{
builtin_print_help(parser, argv[0], stdout_buffer);
@@ -4307,7 +4307,7 @@ int builtin_parse(parser_t &parser, wchar_t **argv)
stdout_buffer.append(errors.at(i).describe(src));
stdout_buffer.push_back(L'\n');
}
-
+
stdout_buffer.append(L"(Reparsed with continue after error)\n");
parse_tree.clear();
errors.clear();
View
2 builtin_set.cpp
@@ -712,7 +712,7 @@ static int builtin_set(parser_t &parser, wchar_t **argv)
retcode = 1;
break;
}
-
+
size_t idx_count = indexes.size();
size_t val_count = argc-woptind-1;
View
6 common.cpp
@@ -1130,7 +1130,7 @@ static size_t read_unquoted_escape(const wchar_t *input, wcstring *result, bool
switch (c)
{
- /* A null character after a backslash is an error */
+ /* A null character after a backslash is an error */
case L'\0':
{
/* Adjust in_pos to only include the backslash */
@@ -1177,11 +1177,11 @@ static size_t read_unquoted_escape(const wchar_t *input, wcstring *result, bool
{
chars=8;
max_val = WCHAR_MAX;
-
+
// Don't exceed the largest Unicode code point - see #1107
if (0x10FFFF < max_val)
max_val = (wchar_t)0x10FFFF;
-
+
break;
}
View
58 complete.cpp
@@ -472,7 +472,7 @@ void completion_autoload_t::command_removed(const wcstring &cmd)
void append_completion(std::vector<completion_t> &completions, const wcstring &comp, const wcstring &desc, complete_flags_t flags, string_fuzzy_match_t match)
{
/* If we just constructed the completion and used push_back, we would get two string copies. Try to avoid that by making a stubby completion in the vector first, and then copying our string in. Note that completion_t's constructor will munge 'flags' so it's important that we pass those to the constructor.
-
+
Nasty hack for #1241 - since the constructor needs the completion string to resolve AUTO_SPACE, and we aren't providing it with the completion, we have to do the resolution ourselves. We should get this resolving out of the constructor.
*/
const wcstring empty;
@@ -1811,56 +1811,56 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> &comps
parse_util_cmdsubst_extent(cmd_with_subcmds.c_str(), cmd_with_subcmds.size(), &cmdsubst_begin, &cmdsubst_end);
assert(cmdsubst_begin != NULL && cmdsubst_end != NULL && cmdsubst_end >= cmdsubst_begin);
const wcstring cmd = wcstring(cmdsubst_begin, cmdsubst_end - cmdsubst_begin);
-
+
/* Make our completer */
completer_t completer(cmd, flags);
-
+
wcstring current_command;
const size_t pos = cmd.size();
bool done=false;
bool use_command = 1;
bool use_function = 1;
bool use_builtin = 1;
-
+
// debug( 1, L"Complete '%ls'", cmd );
-
+
const wchar_t *cmd_cstr = cmd.c_str();
const wchar_t *tok_begin = NULL, *prev_begin = NULL, *prev_end = NULL;
parse_util_token_extent(cmd_cstr, cmd.size(), &tok_begin, NULL, &prev_begin, &prev_end);
-
+
/**
If we are completing a variable name or a tilde expansion user
name, we do that and return. No need for any other completions.
*/
-
+
const wcstring current_token = tok_begin;
-
+
if (!done)
{
done = completer.try_complete_variable(current_token) || completer.try_complete_user(current_token);
}
-
+
if (!done)
{
//const size_t prev_token_len = (prev_begin ? prev_end - prev_begin : 0);
//const wcstring prev_token(prev_begin, prev_token_len);
-
+
parse_node_tree_t tree;
parse_tree_from_string(cmd, parse_flag_continue_after_error | parse_flag_accept_incomplete_tokens, &tree, NULL);
-
+
/* Find the plain statement that contains the position */
const parse_node_t *plain_statement = tree.find_node_matching_source_location(symbol_plain_statement, pos, NULL);
if (plain_statement != NULL)
{
assert(plain_statement->has_source() && plain_statement->type == symbol_plain_statement);
-
+
/* Get the command node */
const parse_node_t *cmd_node = tree.get_child(*plain_statement, 0, parse_token_type_string);
-
+
/* Get the actual command string */
if (cmd_node != NULL)
current_command = cmd_node->get_source(cmd);
-
+
/* Check the decoration */
switch (tree.decoration_for_plain_statement(*plain_statement))
{
@@ -1869,20 +1869,20 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> &comps
use_function = true;
use_builtin = true;
break;
-
+
case parse_statement_decoration_command:
use_command = true;
use_function = false;
use_builtin = false;
break;
-
+
case parse_statement_decoration_builtin:
use_command = false;
use_function = false;
use_builtin = true;
break;
}
-
+
if (cmd_node && cmd_node->location_in_or_at_end_of_source_range(pos))
{
/* Complete command filename */
@@ -1892,7 +1892,7 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> &comps
{
/* Get all the arguments */
const parse_node_tree_t::parse_node_list_t all_arguments = tree.find_nodes(*plain_statement, symbol_argument);
-
+
/* See whether we are in an argument. We may also be in a redirection, or nothing at all. */
size_t matching_arg_index = -1;
for (size_t i=0; i < all_arguments.size(); i++)
@@ -1904,17 +1904,17 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> &comps
break;
}
}
-
+
bool had_ddash = false;
wcstring current_argument, previous_argument;
if (matching_arg_index != (size_t)(-1))
{
/* Get the current argument and the previous argument, if we have one */
current_argument = all_arguments.at(matching_arg_index)->get_source(cmd);
-
+
if (matching_arg_index > 0)
previous_argument = all_arguments.at(matching_arg_index - 1)->get_source(cmd);
-
+
/* Check to see if we have a preceding double-dash */
for (size_t i=0; i < matching_arg_index; i++)
{
@@ -1925,34 +1925,34 @@ void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> &comps
}
}
}
-
+
bool do_file = false;
-
+
wcstring current_command_unescape, previous_argument_unescape, current_argument_unescape;
if (unescape_string(current_command, &current_command_unescape, UNESCAPE_DEFAULT) &&
- unescape_string(previous_argument, &previous_argument_unescape, UNESCAPE_DEFAULT) &&
- unescape_string(current_argument, &current_argument_unescape, UNESCAPE_INCOMPLETE))
+ unescape_string(previous_argument, &previous_argument_unescape, UNESCAPE_DEFAULT) &&
+ unescape_string(current_argument, &current_argument_unescape, UNESCAPE_INCOMPLETE))
{
do_file = completer.complete_param(current_command_unescape,
previous_argument_unescape,
current_argument_unescape,
!had_ddash);
}
-
+
/* If we have found no command specific completions at all, fall back to using file completions. */
if (completer.empty())
do_file = true;
-
+
/* And if we're autosuggesting, and the token is empty, don't do file suggestions */
if ((flags & COMPLETION_REQUEST_AUTOSUGGESTION) && current_argument_unescape.empty())
do_file = false;
-
+
/* This function wants the unescaped string */
completer.complete_param_expand(current_token, do_file);
}
}
}
-
+
comps = completer.get_completions();
}
View
8 env_universal.cpp
@@ -132,12 +132,12 @@ static int try_get_socket_once(void)
if (connect(s, (struct sockaddr *)&local, sizeof local) == -1)
{
close(s);
-
+
/* If it fails on first try, it's probably no serious error, but fishd hasn't been launched yet.
This happens (at least) on the first concurrent session. */
if (get_socket_count > 1)
wperror(L"connect");
-
+
return -1;
}
@@ -438,8 +438,8 @@ void env_universal_set(const wcstring &name, const wcstring &value, bool exportv
else
{
message_t *msg = create_message(exportv?SET_EXPORT:SET,
- name.c_str(),
- value.c_str());
+ name.c_str(),
+ value.c_str());
if (!msg)
{
View
4 event.cpp
@@ -146,13 +146,13 @@ static int event_is_blocked(const event_t &e)
{
const block_t *block;
parser_t &parser = parser_t::principal_parser();
-
+
size_t idx = 0;
while ((block = parser.block_at_index(idx++)))
{
if (event_block_list_blocks_type(block->event_blocks, e.type))
return true;
-
+
}
return event_block_list_blocks_type(parser.global_event_blocks, e.type);
}
View
16 exec.cpp
@@ -582,7 +582,7 @@ static void exec_no_exec(parser_t &parser, const job_t *job)
/* With the new parser, commands aren't responsible for pushing / popping blocks, so there's nothing to do */
return;
}
-
+
/* Hack hack hack. If this is an 'end' job, then trigger a pop. If this is a job that would create a block, trigger a push. See #624 */
const process_t *p = job->first_process;
if (p && p->type == INTERNAL_BUILTIN)
@@ -988,7 +988,7 @@ void exec_job(parser_t &parser, job_t *j)
}
break;
}
-
+
case INTERNAL_BUILTIN:
{
int builtin_stdin=0;
@@ -1133,20 +1133,20 @@ void exec_job(parser_t &parser, job_t *j)
}
break;
}
-
+
case EXTERNAL:
/* External commands are handled in the next switch statement below */
break;
-
+
case INTERNAL_EXEC:
/* We should have handled exec up above */
assert(0 && "INTERNAL_EXEC process found in pipeline, where it should never be. Aborting.");
break;
-
+
case INTERNAL_BUFFER:
/* Internal buffers are handled in the next switch statement below */
break;
-
+
}
if (exec_error)
@@ -1507,7 +1507,7 @@ void exec_job(parser_t &parser, job_t *j)
break;
}
-
+
case INTERNAL_EXEC:
{
/* We should have handled exec up above */
@@ -1581,7 +1581,7 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst, boo
int prev_subshell = is_subshell;
const int prev_status = proc_get_last_status();
char sep=0;
-
+
//fprintf(stderr, "subcmd %ls\n", cmd.c_str());
const env_var_t ifs = env_get_string(L"IFS");
View
4 expand.cpp
@@ -793,7 +793,7 @@ static int expand_pid(const wcstring &instr_with_sep,
append_completion(out, instr_with_sep);
return 1;
}
-
+
/* expand_string calls us with internal separators in instr...sigh */
wcstring instr = instr_with_sep;
remove_internal_separator(instr, false);
@@ -1624,7 +1624,7 @@ wcstring replace_home_directory_with_tilde(const wcstring &str)
{
home_directory.push_back(L'/');
}
-
+
// Now check if the home_directory prefixes the string
if (string_prefixes_string(home_directory, result))
{
View
192 fish_tests.cpp
@@ -149,7 +149,11 @@ static void err(const wchar_t *blah, ...)
/* Test sane escapes */
static void test_unescape_sane()
{
- const struct test_t {const wchar_t * input; const wchar_t * expected;} tests[] =
+ const struct test_t
+ {
+ const wchar_t * input;
+ const wchar_t * expected;
+ } tests[] =
{
{L"abcd", L"abcd"},
{L"'abcd'", L"abcd"},
@@ -439,7 +443,7 @@ static void test_tok()
}
}
}
-
+
/* Test redirection_type_for_string */
if (redirection_type_for_string(L"<") != TOK_REDIRECT_IN) err(L"redirection_type_for_string failed on line %ld", (long)__LINE__);
if (redirection_type_for_string(L"^") != TOK_REDIRECT_OUT) err(L"redirection_type_for_string failed on line %ld", (long)__LINE__);
@@ -623,45 +627,45 @@ static void test_parser()
{
err(L"'break' command outside of loop block context undetected");
}
-
+
if (parse_util_detect_errors(L"break --help"))
{
err(L"'break --help' incorrectly marked as error");
}
-
+
if (! parse_util_detect_errors(L"while false ; function foo ; break ; end ; end "))
{
err(L"'break' command inside function allowed to break from loop outside it");
}
-
+
if (!parse_util_detect_errors(L"exec ls|less") || !parse_util_detect_errors(L"echo|return"))
{
err(L"Invalid pipe command undetected");
}
-
+
if (parse_util_detect_errors(L"for i in foo ; switch $i ; case blah ; break; end; end "))
{
err(L"'break' command inside switch falsely reported as error");
}
-
+
if (parse_util_detect_errors(L"or cat | cat") || parse_util_detect_errors(L"and cat | cat"))
{
err(L"boolean command at beginning of pipeline falsely reported as error");
}
-
+
if (! parse_util_detect_errors(L"cat | and cat"))
{
err(L"'and' command in pipeline not reported as error");
}
-
+
if (! parse_util_detect_errors(L"cat | exec") || ! parse_util_detect_errors(L"exec | cat"))
{
err(L"'exec' command in pipeline not reported as error");
}
-
+
say(L"Testing basic evaluation");
#if 0
@@ -675,7 +679,7 @@ static void test_parser()
{
err(L"Invalid block mode when evaluating undetected");
}
-
+
/* Ensure that we don't crash on infinite self recursion and mutual recursion. These must use the principal parser because we cannot yet execute jobs on other parsers (!) */
say(L"Testing recursion detection");
parser_t::principal_parser().eval(L"function recursive ; recursive ; end ; recursive; ", io_chain_t(), TOP);
@@ -717,70 +721,71 @@ static void test_1_cancellation(const wchar_t *src)
static void test_cancellation()
{
say(L"Testing Ctrl-C cancellation. If this hangs, that's a bug!");
-
+
/* Enable fish's signal handling here. We need to make this interactive for fish to install its signal handlers */
proc_push_interactive(1);
signal_set_handlers();
-
+
/* This tests that we can correctly ctrl-C out of certain loop constructs, and that nothing gets printed if we do */
-
+
/* Here the command substitution is an infinite loop. echo never even gets its argument, so when we cancel we expect no output */
test_1_cancellation(L"echo (while true ; echo blah ; end)");
-
+
fprintf(stderr, ".");
-
+
/* Nasty infinite loop that doesn't actually execute anything */
test_1_cancellation(L"echo (while true ; end) (while true ; end) (while true ; end)");
fprintf(stderr, ".");
-
+
test_1_cancellation(L"while true ; end");
fprintf(stderr, ".");
-
+
test_1_cancellation(L"for i in (while true ; end) ; end");
fprintf(stderr, ".");
fprintf(stderr, "\n");
-
+
/* Restore signal handling */
proc_pop_interactive();
signal_reset_handlers();
-
+
/* Ensure that we don't think we should cancel */
reader_reset_interrupted();
}
static void test_indents()
{
say(L"Testing indents");
-
+
// Here are the components of our source and the indents we expect those to be
- struct indent_component_t {
+ struct indent_component_t
+ {
const wchar_t *txt;
int indent;
};
-
+
const indent_component_t components1[] =
{
{L"if foo", 0},
{L"end", 0},
{NULL, -1}
};
-
+
const indent_component_t components2[] =
{
{L"if foo", 0},
{L"", 1}, //trailing newline!
{NULL, -1}
};
-
+
const indent_component_t components3[] =
{
{L"if foo", 0},
{L"foo", 1},
{L"end", 0}, //trailing newline!
{NULL, -1}
};
-
+
const indent_component_t components4[] =
{
{L"if foo", 0},
@@ -790,31 +795,31 @@ static void test_indents()
{L"", 0},
{NULL, -1}
};
-
+
const indent_component_t components5[] =
{
{L"if foo", 0},
{L"if bar", 1},
{L"", 2},
{NULL, -1}
};
-
+
const indent_component_t components6[] =
{
{L"begin", 0},
{L"foo", 1},
{L"", 1},
{NULL, -1}
};
-
+
const indent_component_t components7[] =
{
{L"begin; end", 0},
{L"foo", 0},
{L"", 0},
{NULL, -1}
};
-
+
const indent_component_t components8[] =
{
{L"if foo", 0},
@@ -831,7 +836,7 @@ static void test_indents()
{L"", 1},
{NULL, -1}
};
-
+
const indent_component_t components10[] =
{
{L"switch foo", 0},
@@ -841,7 +846,7 @@ static void test_indents()
{L"", 2},
{NULL, -1}
};
-
+
const indent_component_t components11[] =
{
{L"switch foo", 0},
@@ -850,7 +855,7 @@ static void test_indents()
};
-
+
const indent_component_t *tests[] = {components1, components2, components3, components4, components5, components6, components7, components8, components9, components10, components11};
for (size_t which = 0; which < sizeof tests / sizeof *tests; which++)
{
@@ -861,7 +866,7 @@ static void test_indents()
{
component_count++;
}
-
+
// Generate the expected indents
wcstring text;
std::vector<int> expected_indents;
@@ -876,10 +881,10 @@ static void test_indents()
expected_indents.resize(text.size(), components[i].indent);
}
assert(expected_indents.size() == text.size());
-
+
// Compute the indents
std::vector<int> indents = parse_util_compute_indents(text);
-
+
if (expected_indents.size() != indents.size())
{
err(L"Indent vector has wrong size! Expected %lu, actual %lu", expected_indents.size(), indents.size());
@@ -990,7 +995,7 @@ static int expand_test(const wchar_t *in, int flags, ...)
size_t i=0;
int res=1;
wchar_t *arg;
-
+
if (expand_string(in, output, flags))
{
@@ -1468,22 +1473,22 @@ static void test_complete(void)
assert(completions.size() == 2);
assert(completions.at(0).completion == L"$Foo1");
assert(completions.at(1).completion == L"$Bar1");
-
+
completions.clear();
complete(L"echo (/bin/mkdi", completions, COMPLETION_REQUEST_DEFAULT);
assert(completions.size() == 1);
assert(completions.at(0).completion == L"r");
-
+
completions.clear();
complete(L"echo (ls /bin/mkdi", completions, COMPLETION_REQUEST_DEFAULT);
assert(completions.size() == 1);
assert(completions.at(0).completion == L"r");
-
+
completions.clear();
complete(L"echo (command ls /bin/mkdi", completions, COMPLETION_REQUEST_DEFAULT);
assert(completions.size() == 1);
assert(completions.at(0).completion == L"r");
-
+
/* Add a function and test completing it in various ways */
struct function_data_t func_data;
func_data.name = L"scuttlebutt";
@@ -1505,7 +1510,7 @@ static void test_complete(void)
completions.clear();
complete(L"echo (builtin scuttlebut", completions, COMPLETION_REQUEST_DEFAULT);
assert(completions.size() == 0);
-
+
complete_set_variable_names(NULL);
}
@@ -2267,13 +2272,13 @@ static void test_new_parser_correctness(void)
static inline bool string_for_permutation(const wcstring *fuzzes, size_t fuzz_count, size_t len, size_t permutation, wcstring *out_str)
{
out_str->clear();
-
+
size_t remaining_permutation = permutation;
for (size_t i=0; i < len; i++)
{
size_t idx = remaining_permutation % fuzz_count;
remaining_permutation /= fuzz_count;
-
+
out_str->append(fuzzes[idx]);
out_str->push_back(L' ');
}
@@ -2307,11 +2312,11 @@ static void test_new_parser_fuzzing(void)
L"&",
L";",
};
-
+
/* Generate a list of strings of all keyword / token combinations. */
wcstring src;
src.reserve(128);
-
+
parse_node_tree_t node_tree;
parse_error_list_t errors;
@@ -2331,7 +2336,7 @@ static void test_new_parser_fuzzing(void)
}
if (log_it)
fprintf(stderr, "done (%lu)\n", permutation);
-
+
}
double end = timef();
if (log_it)
@@ -2344,7 +2349,7 @@ static bool test_1_parse_ll2(const wcstring &src, wcstring *out_cmd, wcstring *o
out_cmd->clear();
out_joined_args->clear();
*out_deco = parse_statement_decoration_none;
-
+
bool result = false;
parse_node_tree_t tree;
if (parse_tree_from_string(src, parse_flag_none, &tree, NULL))
@@ -2357,13 +2362,13 @@ static bool test_1_parse_ll2(const wcstring &src, wcstring *out_cmd, wcstring *o
return false;
}
const parse_node_t &stmt = *stmt_nodes.at(0);
-
+
/* Return its decoration */
*out_deco = tree.decoration_for_plain_statement(stmt);
-
+
/* Return its command */
tree.command_for_plain_statement(stmt, src, out_cmd);
-
+
/* Return arguments separated by spaces */
const parse_node_tree_t::parse_node_list_t arg_nodes = tree.find_nodes(stmt, symbol_argument);
for (size_t i=0; i < arg_nodes.size(); i++)
@@ -2380,7 +2385,7 @@ static bool test_1_parse_ll2(const wcstring &src, wcstring *out_cmd, wcstring *o
static void test_new_parser_ll2(void)
{
say(L"Testing parser two-token lookahead");
-
+
const struct
{
wcstring src;
@@ -2402,7 +2407,7 @@ static void test_new_parser_ll2(void)
{L"function", L"function", L"", parse_statement_decoration_none},
{L"function --help", L"function", L"--help", parse_statement_decoration_none}
};
-
+
for (size_t i=0; i < sizeof tests / sizeof *tests; i++)
{
wcstring cmd, args;
@@ -2417,7 +2422,7 @@ static void test_new_parser_ll2(void)
if (deco != tests[i].deco)
err(L"When parsing '%ls', expected decoration %d but got %d on line %ld", tests[i].src.c_str(), (int)tests[i].deco, (int)deco, (long)__LINE__);
}
-
+
/* Verify that 'function -h' and 'function --help' are plain statements but 'function --foo' is not (#1240) */
const struct
{
@@ -2438,7 +2443,7 @@ static void test_new_parser_ll2(void)
{
err(L"Failed to parse '%ls'", tests2[i].src.c_str());
}
-
+
const parse_node_tree_t::parse_node_list_t node_list = tree.find_nodes(tree.at(0), tests2[i].type);
if (node_list.size() == 0)
{
@@ -2455,7 +2460,7 @@ static void test_new_parser_ad_hoc()
{
/* Very ad-hoc tests for issues encountered */
say(L"Testing new parser ad hoc tests");
-
+
/* Ensure that 'case' terminates a job list */
const wcstring src = L"switch foo ; case bar; case baz; end";
parse_node_tree_t parse_tree;
@@ -2464,7 +2469,7 @@ static void test_new_parser_ad_hoc()
{
err(L"Parsing failed");
}
-
+
/* Expect three case_item_lists: one for each case, and a terminal one. The bug was that we'd try to run a command 'case' */
const parse_node_t &root = parse_tree.at(0);
const parse_node_tree_t::parse_node_list_t node_list = parse_tree.find_nodes(root, symbol_case_item_list);
@@ -2487,33 +2492,33 @@ static void test_new_parser_errors(void)
{L"echo 'abc", parse_error_tokenizer_unterminated_quote},
{L"'", parse_error_tokenizer_unterminated_quote},
{L"echo (abc", parse_error_tokenizer_unterminated_subshell},
-
+
{L"end", parse_error_unbalancing_end},
{L"echo hi ; end", parse_error_unbalancing_end},
-
+
{L"else", parse_error_unbalancing_else},
{L"if true ; end ; else", parse_error_unbalancing_else},
-
+
{L"case", parse_error_unbalancing_case},
{L"if true ; case ; end", parse_error_unbalancing_case},
-
+
{L"foo || bar", parse_error_double_pipe},
{L"foo && bar", parse_error_double_background},
};
-
+
for (size_t i = 0; i < sizeof tests / sizeof *tests; i++)
{
const wcstring src = tests[i].src;
parse_error_code_t expected_code = tests[i].code;
-
+
parse_error_list_t errors;
parse_node_tree_t parse_tree;
bool success = parse_tree_from_string(src, parse_flag_none, &parse_tree, &errors);
if (success)
{
err(L"Source '%ls' was expected to fail to parse, but succeeded", src.c_str());
}
-
+
if (errors.size() != 1)
{
err(L"Source '%ls' was expected to produce 1 error, but instead produced %lu errors", src.c_str(), errors.size());
@@ -2526,9 +2531,9 @@ static void test_new_parser_errors(void)
err(L"\t\t%ls", errors.at(i).describe(src).c_str());
}
}
-
+
}
-
+
}
static void test_highlighting(void)
@@ -2537,21 +2542,22 @@ static void test_highlighting(void)
if (system("mkdir -p /tmp/fish_highlight_test/")) err(L"mkdir failed");
if (system("touch /tmp/fish_highlight_test/foo")) err(L"touch failed");
if (system("touch /tmp/fish_highlight_test/bar")) err(L"touch failed");
-
+
// Here are the components of our source and the colors we expect those to be
- struct highlight_component_t {
+ struct highlight_component_t
+ {
const wchar_t *txt;
int color;
};
-
+
const highlight_component_t components1[] =
{
{L"echo", highlight_spec_command},
{L"/tmp/fish_highlight_test/foo", highlight_spec_param | highlight_modifier_valid_path},
{L"&", highlight_spec_statement_terminator},
{NULL, -1}
};
-
+
const highlight_component_t components2[] =
{
{L"command", highlight_spec_command},
@@ -2561,7 +2567,7 @@ static void test_highlighting(void)
{L"&", highlight_spec_statement_terminator},
{NULL, -1}
};
-
+
const highlight_component_t components3[] =
{
{L"if command ls", highlight_spec_command},
@@ -2574,22 +2580,22 @@ static void test_highlighting(void)
{L"end", highlight_spec_command},
{NULL, -1}
};
-
+
/* Verify that cd shows errors for non-directories */
const highlight_component_t components4[] =
{
{L"cd", highlight_spec_command},
{L"/tmp/fish_highlight_test", highlight_spec_param | highlight_modifier_valid_path},
{NULL, -1}
};
-
+
const highlight_component_t components5[] =
{
{L"cd", highlight_spec_command},
{L"/tmp/fish_highlight_test/foo", highlight_spec_error},
{NULL, -1}
};
-
+
const highlight_component_t components6[] =
{
{L"cd", highlight_spec_command},
@@ -2598,7 +2604,7 @@ static void test_highlighting(void)
{L"definitely_not_a_directory", highlight_spec_error},
{NULL, -1}
};
-
+
// Command substitutions
const highlight_component_t components7[] =
{
@@ -2610,57 +2616,57 @@ static void test_highlighting(void)
{L")", highlight_spec_operator},
{NULL, -1}
};
-
+
// Redirections substitutions
const highlight_component_t components8[] =
{
{L"echo", highlight_spec_command},
{L"param1", highlight_spec_param},
-
+
/* Input redirection */
{L"<", highlight_spec_redirection},
{L"/bin/echo", highlight_spec_redirection},
-
+
/* Output redirection to a valid fd */
{L"1>&2", highlight_spec_redirection},
-
+
/* Output redirection to an invalid fd */
{L"2>&", highlight_spec_redirection},
{L"LOL", highlight_spec_error},
/* Just a param, not a redirection */
{L"/tmp/blah", highlight_spec_param},
-
+
/* Input redirection from directory */
{L"<", highlight_spec_redirection},
{L"/tmp/", highlight_spec_error},
-
+
/* Output redirection to an invalid path */
{L"3>", highlight_spec_redirection},
{L"/not/a/valid/path/nope", highlight_spec_error},
-
+
/* Output redirection to directory */
{L"3>", highlight_spec_redirection},
{L"/tmp/nope/", highlight_spec_error},
-
+
/* Redirections to overflow fd */
{L"99999999999999999999>&2", highlight_spec_error},
{L"2>&", highlight_spec_redirection},
{L"99999999999999999999", highlight_spec_error},
-
+
/* Output redirection containing a command substitution */
{L"4>", highlight_spec_redirection},
{L"(", highlight_spec_operator},
{L"echo", highlight_spec_command},
{L"/tmp/somewhere", highlight_spec_param},
{L")", highlight_spec_operator},
-
+
/* Just another param */
{L"param2", highlight_spec_param},
{NULL, -1}
};
-
+
const highlight_component_t components9[] =
{
{L"end", highlight_spec_error},
@@ -2677,7 +2683,7 @@ static void test_highlighting(void)
{NULL, -1}
};
-
+
const highlight_component_t *tests[] = {components1, components2, components3, components4, components5, components6, components7, components8, components9, components10};
for (size_t which = 0; which < sizeof tests / sizeof *tests; which++)
{
@@ -2688,7 +2694,7 @@ static void test_highlighting(void)
{
component_count++;
}
-
+
// Generate the text
wcstring text;
std::vector<int> expected_colors;
@@ -2703,10 +2709,10 @@ static void test_highlighting(void)
expected_colors.resize(text.size(), components[i].color);
}
assert(expected_colors.size() == text.size());
-
+
std::vector<highlight_spec_t> colors(text.size());
highlight_shell(text, colors, 20, NULL, env_vars_snapshot_t());
-
+
if (expected_colors.size() != colors.size())
{
err(L"Color vector has wrong size! Expected %lu, actual %lu", expected_colors.size(), colors.size());
@@ -2717,15 +2723,15 @@ static void test_highlighting(void)
// Hackish space handling. We don't care about the colors in spaces.
if (text.at(i) == L' ')
continue;
-
+
if (expected_colors.at(i) != colors.at(i))
{
const wcstring spaces(i, L' ');
err(L"Wrong color at index %lu in text (expected %#x, actual %#x):\n%ls\n%ls^", i, expected_colors.at(i), colors.at(i), text.c_str(), spaces.c_str());
}
}
}
-
+
system("rm -Rf /tmp/fish_highlight_test");
}
@@ -2750,7 +2756,7 @@ int main(int argc, char **argv)
builtin_init();
reader_init();
env_init();
-
+
/* Set default signal handlers, so we can ctrl-C out of this */
signal_reset_handlers();
View
2 function.cpp
@@ -194,7 +194,7 @@ void function_add(const function_data_t &data, const parser_t &parser)
{
def_offset = parser.line_number_of_character_at_offset(parser.current_block()->tok_pos);
}
-
+
const function_map_t::value_type new_pair(data.name, function_info_t(data, filename, def_offset, is_autoload));
loaded_functions.insert(new_pair);
View
120 highlight.cpp
@@ -334,7 +334,7 @@ bool plain_statement_get_expanded_command(const wcstring &src, const parse_node_
{
assert(plain_statement.type == symbol_plain_statement);
bool result = false;
-
+
/* Get the command */
wcstring cmd;
if (tree.command_for_plain_statement(plain_statement, src, &cmd))
@@ -702,11 +702,11 @@ static bool has_expand_reserved(const wcstring &str)
static bool autosuggest_parse_command(const wcstring &buff, wcstring *out_expanded_command, parse_node_t *out_last_arg)
{
bool result = false;
-
+
/* Parse the buffer */
parse_node_tree_t parse_tree;
parse_tree_from_string(buff, parse_flag_continue_after_error | parse_flag_accept_incomplete_tokens, &parse_tree, NULL);
-
+
/* Find the last statement */
const parse_node_t *last_statement = parse_tree.find_last_node_of_type(symbol_plain_statement, NULL);
if (last_statement != NULL)
@@ -715,7 +715,7 @@ static bool autosuggest_parse_command(const wcstring &buff, wcstring *out_expand
{
/* We got it */
result = true;
-
+
/* Find the last argument. If we don't get one, return an invalid node. */
const parse_node_t *last_arg = parse_tree.find_last_node_of_type(symbol_argument, last_statement);
if (last_arg != NULL)
@@ -732,7 +732,7 @@ bool autosuggest_suggest_special(const wcstring &str, const wcstring &working_di
{
if (str.empty())
return false;
-
+
ASSERT_IS_BACKGROUND_THREAD();
/* Parse the string */
@@ -1665,51 +1665,51 @@ class highlighter_t
{
/* The string we're highlighting. Note this is a reference memmber variable (to avoid copying)! We must not outlive this! */
const wcstring &buff;
-
+
/* Cursor position */
const size_t cursor_pos;
-
+
/* Environment variables. Again, a reference member variable! */
const env_vars_snapshot_t &vars;
-
+
/* Working directory */
const wcstring working_directory;
-
+
/* The resulting colors */
typedef std::vector<highlight_spec_t> color_array_t;
color_array_t color_array;
-
+
/* The parse tree of the buff */
parse_node_tree_t parse_tree;
-
+
/* Color an argument */
void color_argument(const parse_node_t &node);
-
+
/* Color a redirection */
void color_redirection(const parse_node_t &node);
/* Color the arguments of the given node */
void color_arguments(const parse_node_t &list_node);
-
+
/* Color the redirections of the given node */
void color_redirections(const parse_node_t &list_node);
-
+
/* Color all the children of the command with the given type */
void color_children(const parse_node_t &parent, parse_token_type_t type, int color);
-
+
/* Colors the source range of a node with a given color */
void color_node(const parse_node_t &node, int color);
-
- public:
-
+
+public:
+
/* Constructor */
highlighter_t(const wcstring &str, size_t pos, const env_vars_snapshot_t &ev, const wcstring &wd) : buff(str), cursor_pos(pos), vars(ev), working_directory(wd), color_array(str.size())
{
/* Parse the tree */
this->parse_tree.clear();
parse_tree_from_string(buff, parse_flag_continue_after_error | parse_flag_include_comments, &this->parse_tree, NULL);
}
-
+
/* Perform highlighting, returning an array of colors */
const color_array_t &highlight();
};
@@ -1733,16 +1733,16 @@ void highlighter_t::color_argument(const parse_node_t &node)
{
if (! node.has_source())
return;
-
+
const wcstring arg_str = node.get_source(this->buff);
-
+
/* Get an iterator to the colors associated with the argument */
const size_t arg_start = node.source_start;
const color_array_t::iterator arg_colors = color_array.begin() + arg_start;
/* Color this argument without concern for command substitutions */
color_argument_internal(arg_str, arg_colors);
-
+
/* Now do command substitutions */
size_t cmdsub_cursor = 0, cmdsub_start = 0, cmdsub_end = 0;
wcstring cmdsub_contents;
@@ -1751,28 +1751,28 @@ void highlighter_t::color_argument(const parse_node_t &node)
/* The cmdsub_start is the open paren. cmdsub_end is either the close paren or the end of the string. cmdsub_contents extends from one past cmdsub_start to cmdsub_end */
assert(cmdsub_end > cmdsub_start);
assert(cmdsub_end - cmdsub_start - 1 == cmdsub_contents.size());
-
+
/* Found a command substitution. Compute the position of the start and end of the cmdsub contents, within our overall src. */
const size_t arg_subcmd_start = arg_start + cmdsub_start, arg_subcmd_end = arg_start + cmdsub_end;
-
+
/* Highlight the parens. The open paren must exist; the closed paren may not if it was incomplete. */
assert(cmdsub_start < arg_str.size());
this->color_array.at(arg_subcmd_start) = highlight_spec_operator;
if (arg_subcmd_end < this->buff.size())
this->color_array.at(arg_subcmd_end) = highlight_spec_operator;
-
+
/* Compute the cursor's position within the cmdsub. We must be past the open paren (hence >) but can be at the end of the string or closed paren (hence <=) */
size_t cursor_subpos = CURSOR_POSITION_INVALID;
if (cursor_pos != CURSOR_POSITION_INVALID && cursor_pos > arg_subcmd_start && cursor_pos <= arg_subcmd_end)
{
/* The -1 because the cmdsub_contents does not include the open paren */
cursor_subpos = cursor_pos - arg_subcmd_start - 1;
}
-
+
/* Highlight it recursively. */
highlighter_t cmdsub_highlighter(cmdsub_contents, cursor_subpos, this->vars, this->working_directory);
const color_array_t &subcolors = cmdsub_highlighter.highlight();
-
+
/* Copy out the subcolors back into our array */
assert(subcolors.size() == cmdsub_contents.size());
std::copy(subcolors.begin(), subcolors.end(), this->color_array.begin() + arg_subcmd_start + 1);
@@ -1794,7 +1794,7 @@ static bool node_is_potential_path(const wcstring &src, const parse_node_t &node
/* Big hack: is_potential_path expects a tilde, but unescape_string gives us HOME_DIRECTORY. Put it back. */
if (! token.empty() && token.at(0) == HOME_DIRECTORY)
token.at(0) = L'~';
-
+
const wcstring_list_t working_directory_list(1, working_directory);
result = is_potential_path(token, working_directory_list, PATH_EXPAND_TILDE);
}
@@ -1815,7 +1815,7 @@ void highlighter_t::color_arguments(const parse_node_t &list_node)
cmd_is_cd = (cmd_str == L"cd");
}
}
-
+
/* Find all the arguments of this list */
const parse_node_tree_t::parse_node_list_t nodes = this->parse_tree.find_nodes(list_node, symbol_argument);
@@ -1824,7 +1824,7 @@ void highlighter_t::color_arguments(const parse_node_t &list_node)
const parse_node_t *child = nodes.at(i);
assert(child != NULL && child->type == symbol_argument);
this->color_argument(*child);
-
+
if (cmd_is_cd)
{
/* Mark this as an error if it's not 'help' and not a valid cd path */
@@ -1846,18 +1846,18 @@ void highlighter_t::color_redirection(const parse_node_t &redirection_node)
assert(redirection_node.type == symbol_redirection);
if (! redirection_node.has_source())
return;
-
+
const parse_node_t *redirection_primitive = this->parse_tree.get_child(redirection_node, 0, parse_token_type_redirection); //like 2>
const parse_node_t *redirection_target = this->parse_tree.get_child(redirection_node, 1, parse_token_type_string); //like &1 or file path
-
+
if (redirection_primitive != NULL)
{
wcstring target;
const enum token_type redirect_type = this->parse_tree.type_for_redirection(redirection_node, this->buff, NULL, &target);
-
+
/* We may get a TOK_NONE redirection type, e.g. if the redirection is invalid */
this->color_node(*redirection_primitive, redirect_type == TOK_NONE ? highlight_spec_error : highlight_spec_redirection);
-
+
/* Check if the argument contains a command substitution. If so, highlight it as a param even though it's a command redirection, and don't try to do any other validation. */
if (parse_util_locate_cmdsubst(target.c_str(), NULL, NULL, true) != 0)
{
@@ -1886,34 +1886,34 @@ void highlighter_t::color_redirection(const parse_node_t &redirection_node)
const wchar_t *target_cstr = target.c_str();
wchar_t *end = NULL;
int fd = fish_wcstoi(target_cstr, &end, 10);
-
+
/* The iswdigit check ensures there's no leading whitespace, the *end check ensures the entire string was consumed, and the numeric checks ensure the fd is at least zero and there was no overflow */
target_is_valid = (iswdigit(target_cstr[0]) && *end == L'\0' && fd >= 0 && fd < INT_MAX);
}
break;
-
+
case TOK_REDIRECT_IN:
{
/* Input redirections must have a readable non-directory */
struct stat buf = {};
target_is_valid = ! waccess(target_path, R_OK) && ! wstat(target_path, &buf) && ! S_ISDIR(buf.st_mode);
}
break;
-
+
case TOK_REDIRECT_OUT:
case TOK_REDIRECT_APPEND:
case TOK_REDIRECT_NOCLOB:
{
/* Test whether the file exists, and whether it's writable (possibly after creating it). access() returns failure if the file does not exist. */
bool file_exists = false, file_is_writable = false;
int err = 0;
-
+
struct stat buf = {};
if (wstat(target_path, &buf) < 0)
{
err = errno;
}
-
+
if (string_suffixes_string(L"/", target))
{
/* Redirections to things that are directories is definitely not allowed */
@@ -1930,11 +1930,11 @@ void highlighter_t::color_redirection(const parse_node_t &redirection_node)
{
/* File does not exist. Check if its parent directory is writable. */
wcstring parent = wdirname(target_path);
-
+
/* Ensure that the parent ends with the path separator. This will ensure that we get an error if the parent directory is not really a directory. */
if (! string_suffixes_string(L"/", parent))
parent.push_back(L'/');
-
+
/* Now the file is considered writable if the parent directory is writable */
file_exists = false;
file_is_writable = (0 == waccess(parent, W_OK));
@@ -1945,19 +1945,19 @@ void highlighter_t::color_redirection(const parse_node_t &redirection_node)
file_exists = false;
file_is_writable = false;
}
-
+
/* NOCLOB means that we must not overwrite files that exist */
- target_is_valid = file_is_writable && ! (file_exists && redirect_type == TOK_REDIRECT_NOCLOB);
+ target_is_valid = file_is_writable && !(file_exists && redirect_type == TOK_REDIRECT_NOCLOB);
}
break;
-
+
default:
/* We should not get here, since the node was marked as a redirection, but treat it as an error for paranoia */
target_is_valid = false;
break;
}
}
-
+
if (redirection_target != NULL)
{
this->color_node(*redirection_target, target_is_valid ? highlight_spec_redirection : highlight_spec_error);
@@ -2010,47 +2010,47 @@ static bool command_is_valid(const wcstring &cmd, enum parse_statement_decoratio
command_ok = false;
implicit_cd_ok = false;
}
-
+
/* Check them */
bool is_valid = false;
-
+
/* Builtins */
if (! is_valid && builtin_ok)
is_valid = builtin_exists(cmd);
-
+
/* Functions */
if (! is_valid && function_ok)
is_valid = function_exists_no_autoload(cmd, vars);
-
+
/* Abbreviations */
if (! is_valid && abbreviation_ok)
is_valid = expand_abbreviation(cmd, NULL);
-
+
/* Regular commands */
if (! is_valid && command_ok)
is_valid = path_get_path(cmd, NULL, vars);
-
+
/* Implicit cd */
if (! is_valid && implicit_cd_ok)
is_valid = path_can_be_implicit_cd(cmd, NULL, working_directory.c_str(), vars);
-
+
/* Return what we got */
return is_valid;
}
const highlighter_t::color_array_t & highlighter_t::highlight()
{
ASSERT_IS_BACKGROUND_THREAD();
-
+
const size_t length = buff.size();
assert(this->buff.size() == this->color_array.size());
-
+
if (length == 0)
return color_array;
/* Start out at zero */
std::fill(this->color_array.begin(), this->color_array.end(), 0);
-
+
/* Parse the buffer */
parse_node_tree_t parse_tree;
parse_tree_from_string(buff, parse_flag_continue_after_error | parse_flag_include_comments, &parse_tree, NULL);
@@ -2104,7 +2104,7 @@ const highlighter_t::color_array_t & highlighter_t::highlight()
{
bool is_valid_cmd = false;
wcstring cmd(buff, cmd_node->source_start, cmd_node->source_length);
-
+
/* Try expanding it. If we cannot, it's an error. */
bool expanded = expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES | EXPAND_SKIP_JOBS);
if (expanded && ! has_expand_reserved(cmd))
@@ -2142,7 +2142,7 @@ const highlighter_t::color_array_t & highlighter_t::highlight()
break;
}
}
-
+
if (this->cursor_pos <= this->buff.size())
{
/* If the cursor is over an argument, and that argument is a valid path, underline it */
@@ -2153,7 +2153,7 @@ const highlighter_t::color_array_t & highlighter_t::highlight()
/* Must be an argument with source */
if (node.type != symbol_argument || ! node.has_source())
continue;
-
+
/* See if this node contains the cursor. We check <= source_length so that, when backspacing (and the cursor is just beyond the last token), we may still underline it */
if (this->cursor_pos >= node.source_start && this->cursor_pos - node.source_start <= node.source_length)
{
@@ -2173,15 +2173,15 @@ const highlighter_t::color_array_t & highlighter_t::highlight()
}
}
}
-
+
return color_array;
}
void highlight_shell_new_parser(const wcstring &buff, std::vector<highlight_spec_t> &color, size_t pos, wcstring_list_t *error, const env_vars_snapshot_t &vars)
{
/* Do something sucky and get the current working directory on this background thread. This should really be passed in. */
const wcstring working_directory = env_get_pwd_slash();
-
+
/* Highlight it! */
highlighter_t highlighter(buff, pos, vars, working_directory);
color = highlighter.highlight();
View
8 highlight.h
@@ -28,15 +28,15 @@ enum
highlight_spec_quote, //quoted string
highlight_spec_redirection, //redirection
highlight_spec_autosuggestion, //autosuggestion
-
+
HIGHLIGHT_SPEC_PRIMARY_MASK = 0xFF,
-
+
/* The following values are modifiers */
highlight_modifier_valid_path = 0x100,
-
+
/* Very special value */
highlight_spec_invalid = 0xFFFF
-
+
};
typedef uint32_t highlight_spec_t;
View
2 history.h
@@ -61,7 +61,7 @@ class history_item_t
{
return contents;
}
-
+
bool empty() const
{
return contents.empty();
View
23 parse_constants.h
@@ -47,7 +47,7 @@ enum parse_token_type_t
symbol_redirection,
symbol_optional_background,
-
+
symbol_end_command,
// Terminal types
@@ -56,7 +56,7 @@ enum parse_token_type_t
parse_token_type_redirection,
parse_token_type_background,
parse_token_type_end,
-
+
// Special terminal type that means no more tokens forthcoming
parse_token_type_terminate,
@@ -90,7 +90,7 @@ enum parse_keyword_t
parse_keyword_not,
parse_keyword_command,
parse_keyword_builtin,
-
+
LAST_KEYWORD = parse_keyword_builtin
};
@@ -106,31 +106,32 @@ enum parse_statement_decoration_t
enum parse_error_code_t
{
parse_error_none,
-
+
/* Matching values from enum parser_error */
parse_error_syntax,
parse_error_eval,
parse_error_cmdsubst,
-
+
parse_error_generic, // unclassified error types
-
+
//tokenizer errors
parse_error_tokenizer_unterminated_quote,
parse_error_tokenizer_unterminated_subshell,
parse_error_tokenizer_unterminated_escape,
parse_error_tokenizer_other,
-
+
parse_error_unbalancing_end, //end outside of block
parse_error_unbalancing_else, //else outside of if
parse_error_unbalancing_case, //case outside of switch
-
+
parse_error_double_pipe, // foo || bar, has special error message
parse_error_double_background // foo && bar, has special error message
};
-enum {
- PARSER_TEST_ERROR = 1,
- PARSER_TEST_INCOMPLETE = 2
+enum
+{
+ PARSER_TEST_ERROR = 1,
+ PARSER_TEST_INCOMPLETE = 2
};
typedef unsigned int parser_test_error_bits_t;
View
394 parse_execution.cpp
@@ -1,9 +1,9 @@
/**\file parse_execution.cpp
Provides the "linkage" between a parse_node_tree_t and actual execution structures (job_t, etc.)
-
+
A note on error handling: fish has two kind of errors, fatal parse errors non-fatal runtime errors. A fatal error prevents execution of the entire file, while a non-fatal error skips that job.
-
+
Non-fatal errors are printed as soon as they are encountered; otherwise you would have to wait for the execution to finish to see them.
*/
@@ -71,14 +71,14 @@ const parse_node_t *parse_execution_context_t::infinite_recursive_statement_in_j
{
return NULL;
}
-
+
/* Check to see which function call is forbidden */
if (parser->forbidden_function.empty())
{
return NULL;
}
const wcstring &forbidden_function_name = parser->forbidden_function.back();
-
+
/* Get the first job in the job list. */
const parse_node_t *first_job = tree.next_node_in_node_list(job_list, symbol_job, NULL);
if (first_job == NULL)
@@ -88,10 +88,10 @@ const parse_node_t *parse_execution_context_t::infinite_recursive_statement_in_j
/* Here's the statement node we find that's infinite recursive */
const parse_node_t *infinite_recursive_statement = NULL;
-
+
/* Get the list of statements */
const parse_node_tree_t::parse_node_list_t statements = tree.specific_statements_for_job(*first_job);
-
+
/* Find all the decorated statements. We are interested in statements with no decoration (i.e. not command, not builtin) whose command expands to the forbidden function */
for (size_t i=0; i < statements.size(); i++)
{
@@ -101,19 +101,19 @@ const parse_node_t *parse_execution_context_t::infinite_recursive_statement_in_j
{
continue;
}
-
+
const parse_node_t &plain_statement = tree.find_child(statement, symbol_plain_statement);
if (tree.decoration_for_plain_statement(plain_statement) != parse_statement_decoration_none)
{
/* This statement has a decoration like 'builtin' or 'command', and therefore is not infinite recursion. In particular this is what enables 'wrapper functions' */
continue;
}
-
+
/* Ok, this is an undecorated plain statement. Get and expand its command */
wcstring cmd;
tree.command_for_plain_statement(plain_statement, src, &cmd);
expand_one(cmd, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
-
+
if (cmd == forbidden_function_name)
{
/* This is it */
@@ -125,7 +125,7 @@ const parse_node_t *parse_execution_context_t::infinite_recursive_statement_in_j
break;
}
}
-
+
assert(infinite_recursive_statement == NULL || infinite_recursive_statement->type == symbol_decorated_statement);
return infinite_recursive_statement;
}
@@ -134,10 +134,10 @@ enum process_type_t parse_execution_context_t::process_type_for_command(const pa
{
assert(plain_statement.type == symbol_plain_statement);
enum process_type_t process_type = EXTERNAL;
-
+
/* Determine the process type, which depends on the statement decoration (command, builtin, etc) */
enum parse_statement_decoration_t decoration = tree.decoration_for_plain_statement(plain_statement);
-
+
/* Do the "exec hack" */
if (decoration != parse_statement_decoration_command && cmd == L"exec")
{
@@ -203,7 +203,7 @@ parse_execution_context_t::execution_cancellation_reason_t parse_execution_conte
bool parse_execution_context_t::job_is_simple_block(const parse_node_t &job_node) const
{
assert(job_node.type == symbol_job);
-
+
/* Must have one statement */
const parse_node_t &statement = *get_child(job_node, 0, symbol_statement);
const parse_node_t &specific_statement = *get_child(statement, 0);
@@ -213,36 +213,36 @@ bool parse_execution_context_t::job_is_simple_block(const parse_node_t &job_node
return false;
}
-
+
/* Must be no pipes */
const parse_node_t &continuation = *get_child(job_node, 1, symbol_job_continuation);
if (continuation.child_count > 0)
{
/* Multiple statements in this job, so there's pipes involved */
return false;
}
-
+
/* Check for arguments and redirections. All of the above types have an arguments / redirections list. It must be empty. */
const parse_node_t &args_and_redirections = tree.find_child(specific_statement, symbol_arguments_or_redirections_list);
if (args_and_redirections.child_count > 0)
{
/* Non-empty, we have an argument or redirection */
return false;
}
-
+
/* Ok, we are a simple block! */
return true;
}
parse_execution_result_t parse_execution_context_t::run_if_statement(const parse_node_t &statement)
{
assert(statement.type == symbol_if_statement);
-
+
/* Push an if block */
if_block_t *ib = new if_block_t();
ib->node_offset = this->get_offset(statement);
parser->push_block(ib);
-
+
parse_execution_result_t result = parse_execution_success;
/* We have a sequence of if clauses, with a final else, resulting in a single job list that we execute */
@@ -256,10 +256,10 @@ parse_execution_result_t parse_execution_context_t::run_if_statement(const parse
result = parse_execution_cancelled;
break;
}
-
+
assert(if_clause != NULL && else_clause != NULL);
const parse_node_t &condition = *get_child(*if_clause, 1, symbol_job);
-
+
/* Check the condition. We treat parse_execution_errored here as failure, in accordance with historic behavior */
parse_execution_result_t cond_ret = run_1_job(condition, ib);
bool take_branch = (cond_ret == parse_execution_success) && proc_get_last_status() == EXIT_SUCCESS;
@@ -296,7 +296,7 @@ parse_execution_result_t parse_execution_context_t::run_if_statement(const parse
}
}
}
-
+
/* Execute any job list we got */
if (job_list_to_execute != NULL)
{
@@ -305,117 +305,117 @@ parse_execution_result_t parse_execution_context_t::run_if_statement(const parse
/* Done */
parser->pop_block(ib);
-
+
return result;
}
parse_execution_result_t parse_execution_context_t::run_begin_statement(const parse_node_t &header, const parse_node_t &contents)
{
assert(header.type == symbol_begin_header);
assert(contents.type == symbol_job_list);
-
+
/* Basic begin/end block. Push a scope block. */
scope_block_t *sb = new scope_block_t(BEGIN);
parser->push_block(sb);
-
+
/* Run the job list */
parse_execution_result_t ret = run_job_list(contents, sb);
-
+
/* Pop the block */
parser->pop_block(sb);
-
+
return ret;
- }
+}
/* Define a function */
parse_execution_result_t parse_execution_context_t::run_function_statement(const parse_node_t &header, const parse_node_t &contents)
{
assert(header.type == symbol_function_header);
assert(contents.type == symbol_job_list);
parse_execution_result_t result = parse_execution_success;
-
+
/* Get arguments */
const parse_node_t *unmatched_wildcard = NULL;
wcstring_list_t argument_list = this->determine_arguments(header, &unmatched_wildcard);
-
+
if (unmatched_wildcard != NULL)
{
report_unmatched_wildcard_error(*unmatched_wildcard);
result = parse_execution_errored;
}
-
+
if (result == parse_execution_success)
{
const wcstring contents_str = get_source(contents);
wcstring error_str;
int err = define_function(*parser, argument_list, contents_str, &error_str);
proc_set_last_status(err);
-
+
if (! error_str.empty())
{
this->report_error(header, L"%ls", error_str.c_str());
result = parse_execution_errored;
}
}
return result;
-
+
}
parse_execution_result_t parse_execution_context_t::run_block_statement(const parse_node_t &statement)
{
assert(statement.type == symbol_block_statement);
-
+
const parse_node_t &block_header = *get_child(statement, 0, symbol_block_header); //block header
const parse_node_t &header = *get_child(block_header, 0); //specific header type (e.g. for loop)
const parse_node_t &contents = *get_child(statement, 2, symbol_job_list); //block contents
-
+
parse_execution_result_t ret = parse_execution_success;
switch (header.type)
{
case symbol_for_header:
ret = run_for_statement(header, contents);
break;
-
+
case symbol_while_header:
ret = run_while_statement(header, contents);
break;
-
+
case symbol_function_header:
ret = run_function_statement(header, contents);
break;
-
+
case symbol_begin_header:
ret = run_begin_statement(header, contents);
break;
-
+
default:
fprintf(stderr, "Unexpected block header: %ls\n", header.describe().c_str());
PARSER_DIE();
break;
}
-
+
return ret;
}
parse_execution_result_t parse_execution_context_t::run_for_statement(const parse_node_t &header, const parse_node_t &block_contents)
{
assert(header.type == symbol_for_header);
assert(block_contents.type == symbol_job_list);
-
+
/* Get the variable name: `for var_name in ...` */
const parse_node_t &var_name_node = *get_child(header, 1, parse_token_type_string);
const wcstring for_var_name = get_source(var_name_node);
-
+
/* Get the contents to iterate over. */
const parse_node_t *unmatched_wildcard = NULL;
wcstring_list_t argument_list = this->determine_arguments(header, &unmatched_wildcard);
if (unmatched_wildcard != NULL)
{
return report_unmatched_wildcard_error(*unmatched_wildcard);
}
-
+
parse_execution_result_t ret = parse_execution_success;
-
+
for_block_t *fb = new for_block_t(for_var_name);