aboutsummaryrefslogtreecommitdiffhomepage
path: root/builtin.cpp
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2013-12-20 17:41:21 -0800
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2013-12-20 17:41:21 -0800
commite38217683c65f53fcaa3b6a5daedb6b23b408a90 (patch)
tree18e4abbea0cb72e30d12aab5569c70ceb77f4406 /builtin.cpp
parent12be83562d9096538848a554c4d9f0e0f30f760f (diff)
Refactor block_t storage in parser_t from a linked list to a vector
Diffstat (limited to 'builtin.cpp')
-rw-r--r--builtin.cpp160
1 files changed, 84 insertions, 76 deletions
diff --git a/builtin.cpp b/builtin.cpp
index c1281a52..a5721890 100644
--- a/builtin.cpp
+++ b/builtin.cpp
@@ -831,7 +831,8 @@ static int builtin_block(parser_t &parser, wchar_t **argv)
}
else
{
- block_t *block=parser.current_block;
+ size_t block_idx = 0;
+ block_t *block = parser.block_at_index(block_idx);
event_blockage_t eb = {};
eb.typemask = type;
@@ -840,20 +841,24 @@ static int builtin_block(parser_t &parser, wchar_t **argv)
{
case LOCAL:
{
- if (!block->outer)
- block=0;
+ // If this is the outermost block, then we're global
+ if (block_idx + 1 >= parser.block_count())
+ {
+ block = NULL;
+ }
break;
}
case GLOBAL:
{
- block=0;
+ block=NULL;
}
case UNSET:
{
- while (block &&
- block->type() != FUNCTION_CALL &&
- block->type() != FUNCTION_CALL_NO_SHADOW)
- block = block->outer;
+ while (block != NULL && block->type() != FUNCTION_CALL && block->type() != FUNCTION_CALL_NO_SHADOW)
+ {
+ // Set it in function scope
+ block = parser.block_at_index(++block_idx);
+ }
}
}
if (block)
@@ -1863,18 +1868,21 @@ static int builtin_function(parser_t &parser, wchar_t **argv)
if (is_subshell)
{
- block_t *b = parser.current_block;
-
- while (b && (b->type() != SUBST))
- b = b->outer;
-
- if (b)
+ size_t block_idx = 0;
+
+ /* Find the outermost substitution block */
+ for (block_idx = 0; ; block_idx++)
{
- b=b->outer;
+ const block_t *b = parser.block_at_index(block_idx);
+ if (b == NULL || b->type() == SUBST)
+ break;
}
- if (b->job)
+
+ /* 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)
{
- job_id = b->job->job_id;
+ job_id = caller_block->job->job_id;
}
}
@@ -2058,8 +2066,8 @@ static int builtin_function(parser_t &parser, wchar_t **argv)
}
}
- parser.current_block->tok_pos = parser.get_pos();
- parser.current_block->skip = 1;
+ parser.current_block()->tok_pos = parser.get_pos();
+ parser.current_block()->skip = 1;
return STATUS_BUILTIN_OK;
}
@@ -2712,7 +2720,7 @@ static int builtin_status(parser_t &parser, wchar_t **argv)
case STACK_TRACE:
{
- parser.stack_trace(parser.current_block, stdout_buffer);
+ parser.stack_trace(0, stdout_buffer);
break;
}
@@ -2727,7 +2735,7 @@ static int builtin_status(parser_t &parser, wchar_t **argv)
job_control_mode==JOB_CONTROL_INTERACTIVE?_(L"Only on interactive jobs"):
(job_control_mode==JOB_CONTROL_NONE ? _(L"Never") : _(L"Always")));
- parser.stack_trace(parser.current_block, stdout_buffer);
+ parser.stack_trace(0, stdout_buffer);
break;
}
}
@@ -3413,19 +3421,19 @@ static int builtin_for(parser_t &parser, wchar_t **argv)
}
else
{
- parser.current_block->skip=1;
+ parser.current_block()->skip=1;
}
}
return res;
}
/**
- The begin builtin. Creates a nex block.
+ The begin builtin. Creates a new block.
*/
static int builtin_begin(parser_t &parser, wchar_t **argv)
{
parser.push_block(new scope_block_t(BEGIN));
- parser.current_block->tok_pos = parser.get_pos();
+ parser.current_block()->tok_pos = parser.get_pos();
return proc_get_last_status();
}
@@ -3437,7 +3445,7 @@ static int builtin_begin(parser_t &parser, wchar_t **argv)
*/
static int builtin_end(parser_t &parser, wchar_t **argv)
{
- if (!parser.current_block->outer)
+ if (! parser.block_at_index(1))
{
append_format(stderr_buffer,
_(L"%ls: Not inside of block\n"),
@@ -3455,7 +3463,8 @@ static int builtin_end(parser_t &parser, wchar_t **argv)
*/
bool kill_block = true;
- switch (parser.current_block->type())
+ block_t * const current_block = parser.current_block();
+ switch (current_block->type())
{
case WHILE:
{
@@ -3463,13 +3472,13 @@ static int builtin_end(parser_t &parser, wchar_t **argv)
If this is a while loop, we rewind the loop unless
it's the last lap, in which case we continue.
*/
- if (!(parser.current_block->skip && (parser.current_block->loop_status != LOOP_CONTINUE)))
+ if (!(current_block->skip && (current_block->loop_status != LOOP_CONTINUE)))
{
- parser.current_block->loop_status = LOOP_NORMAL;
- parser.current_block->skip = 0;
+ current_block->loop_status = LOOP_NORMAL;
+ current_block->skip = 0;
kill_block = false;
- parser.set_pos(parser.current_block->tok_pos);
- while_block_t *blk = static_cast<while_block_t *>(parser.current_block);
+ parser.set_pos(current_block->tok_pos);
+ while_block_t *blk = static_cast<while_block_t *>(current_block);
blk->status = WHILE_TEST_AGAIN;
}
@@ -3492,9 +3501,9 @@ static int builtin_end(parser_t &parser, wchar_t **argv)
/*
set loop variable to next element, and rewind to the beginning of the block.
*/
- for_block_t *fb = static_cast<for_block_t *>(parser.current_block);
+ for_block_t *fb = static_cast<for_block_t *>(current_block);
wcstring_list_t &for_vars = fb->sequence;
- if (parser.current_block->loop_status == LOOP_BREAK)
+ if (current_block->loop_status == LOOP_BREAK)
{
for_vars.clear();
}
@@ -3505,18 +3514,18 @@ static int builtin_end(parser_t &parser, wchar_t **argv)
for_vars.pop_back();
const wcstring &for_variable = fb->variable;
env_set(for_variable, val.c_str(), ENV_LOCAL);
- parser.current_block->loop_status = LOOP_NORMAL;
- parser.current_block->skip = 0;
+ current_block->loop_status = LOOP_NORMAL;
+ current_block->skip = 0;
kill_block = false;
- parser.set_pos(parser.current_block->tok_pos);
+ parser.set_pos(current_block->tok_pos);
}
break;
}
case FUNCTION_DEF:
{
- function_def_block_t *fdb = static_cast<function_def_block_t *>(parser.current_block);
+ function_def_block_t *fdb = static_cast<function_def_block_t *>(current_block);
function_data_t &d = fdb->function_data;
if (d.name.empty())
@@ -3535,8 +3544,8 @@ static int builtin_end(parser_t &parser, wchar_t **argv)
for the specified function
*/
- wchar_t *def = wcsndup(parser.get_buffer()+parser.current_block->tok_pos,
- parser.get_job_pos()-parser.current_block->tok_pos);
+ wchar_t *def = wcsndup(parser.get_buffer()+current_block->tok_pos,
+ parser.get_job_pos()-current_block->tok_pos);
d.definition = def;
function_add(d, parser);
@@ -3569,9 +3578,9 @@ static int builtin_else(parser_t &parser, wchar_t **argv)
{
bool block_ok = false;
if_block_t *if_block = NULL;
- if (parser.current_block != NULL && parser.current_block->type() == IF)
+ if (parser.current_block() != NULL && parser.current_block()->type() == IF)
{
- if_block = static_cast<if_block_t *>(parser.current_block);
+ if_block = static_cast<if_block_t *>(parser.current_block());
/* Ensure that we're past IF but not up to an ELSE */
if (if_block->if_expr_evaluated && ! if_block->else_evaluated)
{
@@ -3612,7 +3621,6 @@ static int builtin_break_continue(parser_t &parser, wchar_t **argv)
int is_break = (wcscmp(argv[0],L"break")==0);
int argc = builtin_count_args(argv);
- block_t *b = parser.current_block;
if (argc != 1)
{
@@ -3625,15 +3633,16 @@ static int builtin_break_continue(parser_t &parser, wchar_t **argv)
return STATUS_BUILTIN_ERROR;
}
-
- while ((b != 0) &&
- (b->type() != WHILE) &&
- (b->type() != FOR))
+ /* Find the index of the enclosing for or while loop. Recall that incrementing loop_idx goes 'up' to outer blocks */
+ size_t loop_idx;
+ for (loop_idx = 0; loop_idx < parser.block_count(); loop_idx++)
{
- b = b->outer;
+ const block_t *b = parser.block_at_index(loop_idx);
+ if (b->type() == WHILE || b->type() == FOR)
+ break;
}
- if (b == 0)
+ if (loop_idx >= parser.block_count())
{
append_format(stderr_buffer,
_(L"%ls: Not inside of loop\n"),
@@ -3642,15 +3651,17 @@ static int builtin_break_continue(parser_t &parser, wchar_t **argv)
return STATUS_BUILTIN_ERROR;
}
- b = parser.current_block;
- while ((b->type() != WHILE) &&
- (b->type() != FOR))
+ /* Skip blocks interior to the loop */
+ size_t block_idx = loop_idx;
+ while (block_idx--)
{
- b->skip=1;
- b = b->outer;
+ parser.block_at_index(block_idx)->skip = true;
}
- b->skip=1;
- b->loop_status = is_break?LOOP_BREAK:LOOP_CONTINUE;
+
+ /* Skip the loop itself */
+ block_t *loop_block = parser.block_at_index(loop_idx);
+ loop_block->skip = true;
+ loop_block->loop_status = is_break ? LOOP_BREAK : LOOP_CONTINUE;
return STATUS_BUILTIN_OK;
}
@@ -3679,8 +3690,6 @@ static int builtin_return(parser_t &parser, wchar_t **argv)
int argc = builtin_count_args(argv);
int status = proc_get_last_status();
- block_t *b = parser.current_block;
-
switch (argc)
{
case 1:
@@ -3709,15 +3718,16 @@ static int builtin_return(parser_t &parser, wchar_t **argv)
return STATUS_BUILTIN_ERROR;
}
-
- while ((b != 0) &&
- (b->type() != FUNCTION_CALL &&
- b->type() != FUNCTION_CALL_NO_SHADOW))
+ /* Find the function block */
+ size_t function_block_idx;
+ for (function_block_idx = 0; function_block_idx < parser.block_count(); function_block_idx++)
{
- b = b->outer;
+ const block_t *b = parser.block_at_index(function_block_idx);
+ if (b->type() == FUNCTION_CALL || b->type() == FUNCTION_CALL_NO_SHADOW)
+ break;
}
- if (b == 0)
+ if (function_block_idx >= parser.block_count())
{
append_format(stderr_buffer,
_(L"%ls: Not inside of function\n"),
@@ -3725,17 +3735,15 @@ static int builtin_return(parser_t &parser, wchar_t **argv)
builtin_print_help(parser, argv[0], stderr_buffer);
return STATUS_BUILTIN_ERROR;
}
-
- b = parser.current_block;
- while ((b->type() != FUNCTION_CALL &&
- b->type() != FUNCTION_CALL_NO_SHADOW))
+
+ /* Skip everything up to (and then including) the function block */
+ for (size_t i=0; i < function_block_idx; i++)
{
+ block_t *b = parser.block_at_index(i);
b->mark_as_fake();
- b->skip=1;
- b = b->outer;
+ b->skip = true;
}
- b->skip=1;
-
+ parser.block_at_index(function_block_idx)->skip = true;
return status;
}
@@ -3762,7 +3770,7 @@ static int builtin_switch(parser_t &parser, wchar_t **argv)
else
{
parser.push_block(new switch_block_t(argv[1]));
- parser.current_block->skip=1;
+ parser.current_block()->skip=1;
res = proc_get_last_status();
}
@@ -3779,7 +3787,7 @@ static int builtin_case(parser_t &parser, wchar_t **argv)
int i;
wchar_t *unescaped=0;
- if (parser.current_block->type() != SWITCH)
+ if (parser.current_block()->type() != SWITCH)
{
append_format(stderr_buffer,
_(L"%ls: 'case' command while not in switch block\n"),
@@ -3788,8 +3796,8 @@ static int builtin_case(parser_t &parser, wchar_t **argv)
return STATUS_BUILTIN_ERROR;
}
- parser.current_block->skip = 1;
- switch_block_t *sb = static_cast<switch_block_t *>(parser.current_block);
+ parser.current_block()->skip = 1;
+ switch_block_t *sb = static_cast<switch_block_t *>(parser.current_block());
if (sb->switch_taken)
{
return proc_get_last_status();
@@ -3806,7 +3814,7 @@ static int builtin_case(parser_t &parser, wchar_t **argv)
if (match)
{
- parser.current_block->skip = 0;
+ parser.current_block()->skip = 0;
sb->switch_taken = true;
break;
}