aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Kevin Ballard <kevin@sb.org>2014-09-30 20:58:45 -0700
committerGravatar Kevin Ballard <kevin@sb.org>2014-09-30 20:58:45 -0700
commit3616dd588949b3c8f5d238c315b43b65439bf119 (patch)
tree7b9e6ab0f0fc3a3a29f66f49744e2a1c8fbdfcc7
parent489fb7ec3f13e21d0dd157c0d589e07dfb6ee271 (diff)
Base `status -b` off the parser execution stack
Instead of globally marking the state as "in block" when evaluating blocks/functions, update the "in block" status when pushing/popping blocks on the parser stack. Fixes #1729. On a side note, `status -b` is actually pretty useless, because it always returns 0 inside of a function (even without this patch).
-rw-r--r--exec.cpp4
-rw-r--r--parser.cpp19
-rw-r--r--tests/status.in10
-rw-r--r--tests/status.out2
4 files changed, 30 insertions, 5 deletions
diff --git a/exec.cpp b/exec.cpp
index 59915886..10baa76b 100644
--- a/exec.cpp
+++ b/exec.cpp
@@ -525,9 +525,6 @@ static void internal_exec_helper(parser_t &parser,
return;
}
- int is_block_old=is_block;
- is_block=1;
-
signal_unblock();
if (node_offset == NODE_OFFSET_INVALID)
@@ -544,7 +541,6 @@ static void internal_exec_helper(parser_t &parser,
morphed_chain.clear();
io_cleanup_fds(opened_fds);
job_reap(0);
- is_block=is_block_old;
}
/* Returns whether we can use posix spawn for a given process in a given job.
diff --git a/parser.cpp b/parser.cpp
index 3740f1fb..be7e494a 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -278,6 +278,12 @@ void parser_t::push_block(block_t *new_current)
this->block_stack.push_back(new_current);
+ // Types TOP and SUBST are not considered blocks for the purposes of `status -b`
+ if (type != TOP && type != SUBST)
+ {
+ is_block = 1;
+ }
+
if ((new_current->type() != FUNCTION_DEF) &&
(new_current->type() != FAKE) &&
(new_current->type() != TOP))
@@ -305,6 +311,19 @@ void parser_t::pop_block()
env_pop();
delete old;
+
+ // Figure out if `status -b` should consider us to be in a block now
+ int new_is_block=0;
+ for (std::vector<block_t*>::const_iterator it = block_stack.begin(), end = block_stack.end(); it != end; ++it)
+ {
+ const enum block_type_t type = (*it)->type();
+ if (type != TOP && type != SUBST)
+ {
+ new_is_block = 1;
+ break;
+ }
+ }
+ is_block = new_is_block;
}
void parser_t::pop_block(const block_t *expected)
diff --git a/tests/status.in b/tests/status.in
index 14dff232..875f62f3 100644
--- a/tests/status.in
+++ b/tests/status.in
@@ -1,9 +1,17 @@
# vim: set filetype=fish:
+status -b
+or echo 'top level'
+
+begin
+ status -b
+end
+and echo 'block'
+
# Issue #1728
# Bad file redirection on a block causes `status --is-block` to return 0 forever.
begin; end >/ # / is a directory, it can't be opened for writing
status -b
-and echo 'block'
+and echo 'unexpected block'
true
diff --git a/tests/status.out b/tests/status.out
index e69de29b..a6546ffd 100644
--- a/tests/status.out
+++ b/tests/status.out
@@ -0,0 +1,2 @@
+top level
+block