mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 04:43:10 +00:00
Teach fish how to push and pop blocks even in the face of no_exec. All tests finally pass.
https://github.com/fish-shell/fish-shell/issues/624
This commit is contained in:
parent
d146f578a4
commit
b04e874e43
4 changed files with 43 additions and 11 deletions
10
builtin.cpp
10
builtin.cpp
|
@ -211,6 +211,10 @@ static int count_char(const wchar_t *str, wchar_t c)
|
||||||
|
|
||||||
wcstring builtin_help_get(parser_t &parser, const wchar_t *name)
|
wcstring builtin_help_get(parser_t &parser, const wchar_t *name)
|
||||||
{
|
{
|
||||||
|
/* This won't ever work if no_exec is set */
|
||||||
|
if (no_exec)
|
||||||
|
return wcstring();
|
||||||
|
|
||||||
wcstring_list_t lst;
|
wcstring_list_t lst;
|
||||||
wcstring out;
|
wcstring out;
|
||||||
const wcstring name_esc = escape_string(name, 1);
|
const wcstring name_esc = escape_string(name, 1);
|
||||||
|
@ -3481,7 +3485,7 @@ static int builtin_end(parser_t &parser, wchar_t **argv)
|
||||||
are rewinding a loop, this should be set to false, so that
|
are rewinding a loop, this should be set to false, so that
|
||||||
variables in the current loop scope won't die between laps.
|
variables in the current loop scope won't die between laps.
|
||||||
*/
|
*/
|
||||||
int kill_block = 1;
|
bool kill_block = true;
|
||||||
|
|
||||||
switch (parser.current_block->type())
|
switch (parser.current_block->type())
|
||||||
{
|
{
|
||||||
|
@ -3495,7 +3499,7 @@ static int builtin_end(parser_t &parser, wchar_t **argv)
|
||||||
{
|
{
|
||||||
parser.current_block->loop_status = LOOP_NORMAL;
|
parser.current_block->loop_status = LOOP_NORMAL;
|
||||||
parser.current_block->skip = 0;
|
parser.current_block->skip = 0;
|
||||||
kill_block = 0;
|
kill_block = false;
|
||||||
parser.set_pos(parser.current_block->tok_pos);
|
parser.set_pos(parser.current_block->tok_pos);
|
||||||
while_block_t *blk = static_cast<while_block_t *>(parser.current_block);
|
while_block_t *blk = static_cast<while_block_t *>(parser.current_block);
|
||||||
blk->status = WHILE_TEST_AGAIN;
|
blk->status = WHILE_TEST_AGAIN;
|
||||||
|
@ -3536,7 +3540,7 @@ static int builtin_end(parser_t &parser, wchar_t **argv)
|
||||||
parser.current_block->loop_status = LOOP_NORMAL;
|
parser.current_block->loop_status = LOOP_NORMAL;
|
||||||
parser.current_block->skip = 0;
|
parser.current_block->skip = 0;
|
||||||
|
|
||||||
kill_block = 0;
|
kill_block = false;
|
||||||
parser.set_pos(parser.current_block->tok_pos);
|
parser.set_pos(parser.current_block->tok_pos);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
36
exec.cpp
36
exec.cpp
|
@ -538,6 +538,37 @@ static bool can_use_posix_spawn_for_job(const job_t *job, const process_t *proce
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* What exec does if no_exec is set. This only has to handle block pushing and popping. See #624. */
|
||||||
|
static void exec_no_exec(parser_t &parser, const job_t *job)
|
||||||
|
{
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
const wchar_t *builtin_name_cstr = p->argv0();
|
||||||
|
if (builtin_name_cstr != NULL)
|
||||||
|
{
|
||||||
|
const wcstring builtin_name = builtin_name_cstr;
|
||||||
|
if (contains(builtin_name, L"for", L"function", L"begin", L"switch"))
|
||||||
|
{
|
||||||
|
// The above builtins are the ones that produce an unbalanced block from within their function implementation
|
||||||
|
// This list should be maintained somewhere else
|
||||||
|
parser.push_block(new fake_block_t());
|
||||||
|
}
|
||||||
|
else if (builtin_name == L"end")
|
||||||
|
{
|
||||||
|
if (parser.current_block == NULL || parser.current_block->type() == TOP)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Warning: not popping the root block\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parser.pop_block();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void exec(parser_t &parser, job_t *j)
|
void exec(parser_t &parser, job_t *j)
|
||||||
{
|
{
|
||||||
|
@ -559,8 +590,10 @@ void exec(parser_t &parser, job_t *j)
|
||||||
CHECK(j,);
|
CHECK(j,);
|
||||||
CHECK_BLOCK();
|
CHECK_BLOCK();
|
||||||
|
|
||||||
if (no_exec)
|
if (no_exec) {
|
||||||
|
exec_no_exec(parser, j);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
sigemptyset(&chldset);
|
sigemptyset(&chldset);
|
||||||
sigaddset(&chldset, SIGCHLD);
|
sigaddset(&chldset, SIGCHLD);
|
||||||
|
@ -1269,7 +1302,6 @@ void exec(parser_t &parser, job_t *j)
|
||||||
p->pid = pid;
|
p->pid = pid;
|
||||||
|
|
||||||
set_child_group(j, p, 0);
|
set_child_group(j, p, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
fish: Expected redirection specification, got token of type '$i'
|
|
||||||
/usr/local/src/grissioms-fish-shell/tests/test.fish (line 51): ../fish <$i >tmp.out ^tmp.err
|
|
||||||
^
|
|
||||||
fish: Expected redirection specification, got token of type '$i'
|
|
||||||
/usr/local/src/grissioms-fish-shell/tests/test.fish (line 51): ../fish <$i >tmp.out ^tmp.err
|
|
||||||
^
|
|
|
@ -1,4 +1,5 @@
|
||||||
Testing high level script functionality
|
Testing high level script functionality
|
||||||
|
File printf.in tested ok
|
||||||
File test1.in tested ok
|
File test1.in tested ok
|
||||||
File test2.in tested ok
|
File test2.in tested ok
|
||||||
File test3.in tested ok
|
File test3.in tested ok
|
||||||
|
@ -7,3 +8,4 @@ File test5.in tested ok
|
||||||
File test6.in tested ok
|
File test6.in tested ok
|
||||||
File test7.in tested ok
|
File test7.in tested ok
|
||||||
File test8.in tested ok
|
File test8.in tested ok
|
||||||
|
File test9.in tested ok
|
||||||
|
|
Loading…
Reference in a new issue