mirror of
https://github.com/fish-shell/fish-shell.git
synced 2025-02-21 02:45:53 +08:00
First stab at getting rid of the ugly state1, state2 properties of block_t
This commit is contained in:
parent
b5e92a831b
commit
96046ffd30
85
builtin.cpp
85
builtin.cpp
@ -824,7 +824,7 @@ static int builtin_block( parser_t &parser, wchar_t **argv )
|
||||
{
|
||||
block_t *block=parser.current_block;
|
||||
|
||||
event_block_t eb = {};
|
||||
event_blockage_t eb = {};
|
||||
eb.typemask = type;
|
||||
|
||||
switch( scope )
|
||||
@ -1530,7 +1530,8 @@ static int builtin_function( parser_t &parser, wchar_t **argv )
|
||||
|
||||
woptind=0;
|
||||
|
||||
parser.push_block( FUNCTION_DEF );
|
||||
block_t *newv = new block_t(FUNCTION_DEF);
|
||||
parser.push_block( newv );
|
||||
|
||||
static const struct woption
|
||||
long_options[] =
|
||||
@ -1729,7 +1730,7 @@ static int builtin_function( parser_t &parser, wchar_t **argv )
|
||||
|
||||
case 'h':
|
||||
parser.pop_block();
|
||||
parser.push_block( FAKE );
|
||||
parser.push_block( new block_t(FAKE) );
|
||||
builtin_print_help( parser, argv[0], stdout_buffer );
|
||||
return STATUS_BUILTIN_OK;
|
||||
|
||||
@ -1834,7 +1835,7 @@ static int builtin_function( parser_t &parser, wchar_t **argv )
|
||||
stderr_buffer.push_back(L'\n');
|
||||
|
||||
parser.pop_block();
|
||||
parser.push_block( FAKE );
|
||||
parser.push_block( new block_t(FAKE) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2869,13 +2870,9 @@ static int builtin_source( parser_t &parser, wchar_t ** argv )
|
||||
|
||||
}
|
||||
|
||||
parser.push_block( SOURCE );
|
||||
parser.push_block( new source_block_t(fn_intern) );
|
||||
reader_push_current_filename( fn_intern );
|
||||
|
||||
// PCA We need the state to be a wcstring; it would be nice to figure out how to restore this optimization however
|
||||
//parser.current_block->state1<const wchar_t *>() = fn_intern;
|
||||
parser.current_block->state1<wcstring>() = fn_intern;
|
||||
|
||||
|
||||
parse_util_set_argv( (argc>2)?(argv+2):(argv+1), wcstring_list_t());
|
||||
|
||||
res = reader_read( fd, real_io ? *real_io : io_chain_t() );
|
||||
@ -3207,24 +3204,23 @@ static int builtin_for( parser_t &parser, wchar_t **argv )
|
||||
|
||||
if( res )
|
||||
{
|
||||
parser.push_block( FAKE );
|
||||
parser.push_block( new block_t(FAKE) );
|
||||
}
|
||||
else
|
||||
{
|
||||
parser.push_block( FOR );
|
||||
const wchar_t *for_variable = argv[1];
|
||||
for_block_t *fb = new for_block_t(for_variable);
|
||||
parser.push_block( fb );
|
||||
fb->tok_pos = parser.get_pos();
|
||||
|
||||
int i;
|
||||
const wcstring for_variable = argv[1];
|
||||
parser.current_block->tok_pos = parser.get_pos();
|
||||
parser.current_block->state1<wcstring>() = for_variable;
|
||||
|
||||
wcstring_list_t &for_vars = parser.current_block->state2<wcstring_list_t>();
|
||||
for( i=argc-1; i>3; i-- )
|
||||
/* Note that we store the sequence of values in opposite order */
|
||||
wcstring_list_t &for_vars = fb->sequence;
|
||||
for( int i=argc-1; i>3; i-- )
|
||||
for_vars.push_back(argv[i]);
|
||||
|
||||
if( argc > 3 )
|
||||
{
|
||||
env_set( for_variable.c_str(), argv[3], ENV_LOCAL );
|
||||
env_set( for_variable, argv[3], ENV_LOCAL );
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3239,7 +3235,7 @@ static int builtin_for( parser_t &parser, wchar_t **argv )
|
||||
*/
|
||||
static int builtin_begin( parser_t &parser, wchar_t **argv )
|
||||
{
|
||||
parser.push_block( BEGIN );
|
||||
parser.push_block( new block_t(BEGIN) );
|
||||
parser.current_block->tok_pos = parser.get_pos();
|
||||
return proc_get_last_status();
|
||||
}
|
||||
@ -3284,7 +3280,8 @@ static int builtin_end( parser_t &parser, wchar_t **argv )
|
||||
parser.current_block->skip = 0;
|
||||
kill_block = 0;
|
||||
parser.set_pos( parser.current_block->tok_pos);
|
||||
parser.current_block->state1<int>() = WHILE_TEST_AGAIN;
|
||||
while_block_t *blk = static_cast<while_block_t *>(parser.current_block);
|
||||
blk->status = WHILE_TEST_AGAIN;
|
||||
}
|
||||
|
||||
break;
|
||||
@ -3304,7 +3301,8 @@ static int builtin_end( parser_t &parser, wchar_t **argv )
|
||||
/*
|
||||
set loop variable to next element, and rewind to the beginning of the block.
|
||||
*/
|
||||
wcstring_list_t &for_vars = parser.current_block->state2<wcstring_list_t>();
|
||||
for_block_t *fb = static_cast<for_block_t *>(parser.current_block);
|
||||
wcstring_list_t &for_vars = fb->sequence;
|
||||
if( parser.current_block->loop_status == LOOP_BREAK )
|
||||
{
|
||||
for_vars.clear();
|
||||
@ -3314,7 +3312,7 @@ static int builtin_end( parser_t &parser, wchar_t **argv )
|
||||
{
|
||||
const wcstring val = for_vars.back();
|
||||
for_vars.pop_back();
|
||||
const wcstring for_variable = parser.current_block->state1<wcstring>();
|
||||
const wcstring &for_variable = fb->variable;
|
||||
env_set( for_variable.c_str(), val.c_str(), ENV_LOCAL);
|
||||
parser.current_block->loop_status = LOOP_NORMAL;
|
||||
parser.current_block->skip = 0;
|
||||
@ -3385,9 +3383,18 @@ static int builtin_end( parser_t &parser, wchar_t **argv )
|
||||
*/
|
||||
static int builtin_else( parser_t &parser, wchar_t **argv )
|
||||
{
|
||||
if( parser.current_block == 0 ||
|
||||
parser.current_block->type != IF ||
|
||||
parser.current_block->state1<int>() != 1)
|
||||
bool block_ok = false;
|
||||
if_block_t *if_block = NULL;
|
||||
if (parser.current_block != NULL && parser.current_block->type == IF)
|
||||
{
|
||||
if_block = static_cast<if_block_t *>(parser.current_block);
|
||||
if (if_block->if_expr_evaluated && ! if_block->else_evaluated)
|
||||
{
|
||||
block_ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( ! block_ok )
|
||||
{
|
||||
append_format(stderr_buffer,
|
||||
_( L"%ls: Not inside of 'if' block\n" ),
|
||||
@ -3397,9 +3404,9 @@ static int builtin_else( parser_t &parser, wchar_t **argv )
|
||||
}
|
||||
else
|
||||
{
|
||||
int &if_state = parser.current_block->state1<int>();
|
||||
if_state++;
|
||||
parser.current_block->skip = !parser.current_block->skip;
|
||||
/* If the 'if' expression evaluated to false, then we ought to take the else branch, which means skip ought to be false. So the sense of the skip variable matches the sense of the 'if' expression result. */
|
||||
if_block->skip = if_block->if_expr_result;
|
||||
if_block->else_evaluated = true;
|
||||
env_pop();
|
||||
env_push(0);
|
||||
}
|
||||
@ -3462,13 +3469,13 @@ static int builtin_break_continue( parser_t &parser, wchar_t **argv )
|
||||
}
|
||||
|
||||
/**
|
||||
Implementation of the builtin count command, used to launch the
|
||||
Implementation of the builtin breakpoint command, used to launch the
|
||||
interactive debugger.
|
||||
*/
|
||||
|
||||
static int builtin_breakpoint( parser_t &parser, wchar_t **argv )
|
||||
{
|
||||
parser.push_block( BREAKPOINT );
|
||||
parser.push_block( new block_t(BREAKPOINT) );
|
||||
|
||||
reader_read( STDIN_FILENO, real_io ? *real_io : io_chain_t() );
|
||||
|
||||
@ -3564,14 +3571,12 @@ static int builtin_switch( parser_t &parser, wchar_t **argv )
|
||||
|
||||
builtin_print_help( parser, argv[0], stderr_buffer );
|
||||
res=1;
|
||||
parser.push_block( FAKE );
|
||||
parser.push_block( new block_t(FAKE) );
|
||||
}
|
||||
else
|
||||
{
|
||||
parser.push_block( SWITCH );
|
||||
parser.current_block->state1<wcstring>() = argv[1];
|
||||
parser.push_block( new switch_block_t(argv[1]) );
|
||||
parser.current_block->skip=1;
|
||||
parser.current_block->state2<int>() = 0;
|
||||
res = proc_get_last_status();
|
||||
}
|
||||
|
||||
@ -3598,25 +3603,25 @@ static int builtin_case( parser_t &parser, wchar_t **argv )
|
||||
}
|
||||
|
||||
parser.current_block->skip = 1;
|
||||
|
||||
if( parser.current_block->state2<int>() )
|
||||
switch_block_t *sb = static_cast<switch_block_t *>(parser.current_block);
|
||||
if( sb->switch_taken )
|
||||
{
|
||||
return proc_get_last_status();
|
||||
}
|
||||
|
||||
const wcstring &switch_value = sb->switch_value;
|
||||
for( i=1; i<argc; i++ )
|
||||
{
|
||||
int match;
|
||||
|
||||
unescaped = parse_util_unescape_wildcards( argv[i] );
|
||||
const wcstring &switch_value = parser.current_block->state1<wcstring>();
|
||||
match = wildcard_match( switch_value, unescaped );
|
||||
free( unescaped );
|
||||
|
||||
if( match )
|
||||
{
|
||||
parser.current_block->skip = 0;
|
||||
parser.current_block->state2<int>() = 1;
|
||||
sb->switch_taken = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -452,8 +452,9 @@ static void event_fire_internal( const event_t *event )
|
||||
proc_push_interactive(0);
|
||||
prev_status = proc_get_last_status();
|
||||
parser_t &parser = parser_t::principal_parser();
|
||||
parser.push_block( EVENT );
|
||||
parser.current_block->state1<const event_t *>() = event;
|
||||
|
||||
block_t *block = new event_block_t(event);
|
||||
parser.push_block(block);
|
||||
parser.eval( buffer, io_chain_t(), TOP );
|
||||
parser.pop_block();
|
||||
proc_pop_interactive();
|
||||
|
8
exec.cpp
8
exec.cpp
@ -758,11 +758,9 @@ void exec( parser_t &parser, job_t *j )
|
||||
debug( 0, _( L"Unknown function '%ls'" ), p->argv0() );
|
||||
break;
|
||||
}
|
||||
parser.push_block( shadows?FUNCTION_CALL:FUNCTION_CALL_NO_SHADOW );
|
||||
|
||||
parser.current_block->state2<process_t *>() = p;
|
||||
parser.current_block->state1<wcstring>() = p->argv0();
|
||||
|
||||
function_block_t *newv = new function_block_t(p, p->argv0(), shadows);
|
||||
parser.push_block( newv );
|
||||
|
||||
|
||||
/*
|
||||
set_argv might trigger an event
|
||||
|
107
parser.cpp
107
parser.cpp
@ -420,16 +420,15 @@ static int block_count( block_t *b )
|
||||
}
|
||||
*/
|
||||
|
||||
void parser_t::push_block( int type )
|
||||
void parser_t::push_block( block_t *newv )
|
||||
{
|
||||
block_t zerod = {};
|
||||
block_t *newv = new block_t(zerod);
|
||||
|
||||
const int type = newv->type;
|
||||
newv->src_lineno = parser_t::get_lineno();
|
||||
newv->src_filename = parser_t::current_filename()?intern(parser_t::current_filename()):0;
|
||||
|
||||
newv->outer = current_block;
|
||||
newv->type = (current_block && current_block->skip)?FAKE:type;
|
||||
if (current_block && current_block->skip)
|
||||
newv->type = FAKE;
|
||||
|
||||
/*
|
||||
New blocks should be skipped if the outer block is skipped,
|
||||
@ -893,7 +892,8 @@ void parser_t::stack_trace( block_t *b, wcstring &buff)
|
||||
/*
|
||||
This is an event handler
|
||||
*/
|
||||
wcstring description = event_get_desc( b->state1<const event_t *>() );
|
||||
const event_block_t *eb = static_cast<const event_block_t *>(b);
|
||||
wcstring description = event_get_desc( eb->event );
|
||||
append_format( buff, _(L"in event handler: %ls\n"), description.c_str());
|
||||
buff.append( L"\n" );
|
||||
|
||||
@ -920,14 +920,15 @@ void parser_t::stack_trace( block_t *b, wcstring &buff)
|
||||
{
|
||||
case SOURCE:
|
||||
{
|
||||
const wcstring &source_dest = b->state1<wcstring>();
|
||||
append_format( buff, _(L"in . (source) call of file '%ls',\n"), source_dest.c_str() );
|
||||
const source_block_t *sb = static_cast<const source_block_t*>(b);
|
||||
const wchar_t *source_dest = sb->source_file;
|
||||
append_format( buff, _(L"in . (source) call of file '%ls',\n"), source_dest );
|
||||
break;
|
||||
}
|
||||
case FUNCTION_CALL:
|
||||
{
|
||||
const wcstring &function_call_name = b->state1<wcstring>();
|
||||
append_format( buff, _(L"in function '%ls',\n"), function_call_name.c_str() );
|
||||
const function_block_t *fb = static_cast<const function_block_t*>(b);
|
||||
append_format( buff, _(L"in function '%ls',\n"), fb->name.c_str() );
|
||||
break;
|
||||
}
|
||||
case SUBST:
|
||||
@ -953,8 +954,9 @@ void parser_t::stack_trace( block_t *b, wcstring &buff)
|
||||
}
|
||||
|
||||
if( b->type == FUNCTION_CALL )
|
||||
{
|
||||
const process_t * const process = b->state2<process_t*>();
|
||||
{
|
||||
const function_block_t *fb = static_cast<const function_block_t *>(b);
|
||||
const process_t * const process = fb->process;
|
||||
if( process->argv(1) )
|
||||
{
|
||||
wcstring tmp;
|
||||
@ -999,8 +1001,8 @@ const wchar_t *parser_t::is_function() const
|
||||
}
|
||||
if( b->type == FUNCTION_CALL )
|
||||
{
|
||||
result = b->state1<wcstring>();
|
||||
return result.c_str();
|
||||
const function_block_t *fb = static_cast<const function_block_t *>(b);
|
||||
return fb->name.c_str();
|
||||
}
|
||||
b=b->outer;
|
||||
}
|
||||
@ -1051,8 +1053,8 @@ const wchar_t *parser_t::current_filename() const
|
||||
}
|
||||
if( b->type == FUNCTION_CALL )
|
||||
{
|
||||
wcstring function_call_name = b->state1<wcstring>();
|
||||
return function_get_definition_file(function_call_name);
|
||||
const function_block_t *fb = static_cast<const function_block_t *>(b);
|
||||
return function_get_definition_file(fb->name);
|
||||
}
|
||||
b=b->outer;
|
||||
}
|
||||
@ -1849,27 +1851,29 @@ int parser_t::parse_job( process_t *p,
|
||||
}
|
||||
else if( nxt == L"while" )
|
||||
{
|
||||
int new_block = 0;
|
||||
bool new_block = false;
|
||||
tok_next( tok );
|
||||
while_block_t *wb = NULL;
|
||||
|
||||
if( ( current_block->type != WHILE ) )
|
||||
{
|
||||
new_block = 1;
|
||||
new_block = true;
|
||||
}
|
||||
else if( current_block->state1<int>() == WHILE_TEST_AGAIN )
|
||||
else if( (wb = static_cast<while_block_t*>(current_block))->status == WHILE_TEST_AGAIN )
|
||||
{
|
||||
current_block->state1<int>() = WHILE_TEST_FIRST;
|
||||
wb->status = WHILE_TEST_FIRST;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_block = 1;
|
||||
new_block = true;
|
||||
}
|
||||
|
||||
if( new_block )
|
||||
{
|
||||
this->push_block( WHILE );
|
||||
current_block->state1<int>() = WHILE_TEST_FIRST;
|
||||
current_block->tok_pos = mark;
|
||||
while_block_t *wb = new while_block_t();
|
||||
wb->status = WHILE_TEST_FIRST;
|
||||
wb->tok_pos = mark;
|
||||
this->push_block( wb );
|
||||
}
|
||||
|
||||
consumed=1;
|
||||
@ -1880,10 +1884,9 @@ int parser_t::parse_job( process_t *p,
|
||||
{
|
||||
tok_next( tok );
|
||||
|
||||
this->push_block( IF );
|
||||
|
||||
current_block->state1<int>()=0;
|
||||
current_block->tok_pos = mark;
|
||||
if_block_t *ib = new if_block_t();
|
||||
this->push_block( ib );
|
||||
ib->tok_pos = mark;
|
||||
|
||||
is_new_block=1;
|
||||
consumed=1;
|
||||
@ -2246,7 +2249,7 @@ void parser_t::skipped_exec( job_t * j )
|
||||
( wcscmp( p->argv0(), L"begin" )==0) ||
|
||||
( wcscmp( p->argv0(), L"function" )==0))
|
||||
{
|
||||
this->push_block( FAKE );
|
||||
this->push_block( new block_t(FAKE) );
|
||||
}
|
||||
else if( wcscmp( p->argv0(), L"end" )==0)
|
||||
{
|
||||
@ -2260,7 +2263,7 @@ void parser_t::skipped_exec( job_t * j )
|
||||
else if( wcscmp( p->argv0(), L"else" )==0)
|
||||
{
|
||||
if( (current_block->type == IF ) &&
|
||||
(current_block->state1<int>() != 0))
|
||||
(static_cast<const if_block_t*>(current_block)->if_expr_evaluated))
|
||||
{
|
||||
exec( *this, j );
|
||||
return;
|
||||
@ -2394,15 +2397,15 @@ void parser_t::eval_job( tokenizer *tok )
|
||||
|
||||
if( current_block->type == WHILE )
|
||||
{
|
||||
|
||||
switch( current_block->state1<int>() )
|
||||
while_block_t *wb = static_cast<while_block_t *>(current_block);
|
||||
switch( wb->status )
|
||||
{
|
||||
case WHILE_TEST_FIRST:
|
||||
{
|
||||
// PCA I added the 'current_block->skip ||' part because we couldn't reliably
|
||||
// control-C out of loops like this: while test 1 -eq 1; end
|
||||
current_block->skip = current_block->skip || proc_get_last_status()!= 0;
|
||||
current_block->state1<int>()=WHILE_TESTED;
|
||||
wb->skip = wb->skip || proc_get_last_status()!= 0;
|
||||
wb->status = WHILE_TESTED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2410,11 +2413,14 @@ void parser_t::eval_job( tokenizer *tok )
|
||||
|
||||
if( current_block->type == IF )
|
||||
{
|
||||
if( (!current_block->state1<int>()) &&
|
||||
if_block_t *ib = static_cast<if_block_t *>(current_block);
|
||||
if( (! ib->if_expr_evaluated) &&
|
||||
(!current_block->skip) )
|
||||
{
|
||||
current_block->skip = proc_get_last_status()!= 0;
|
||||
current_block->state1<int>()++;
|
||||
bool if_result = (proc_get_last_status() == 0);
|
||||
ib->if_expr_result = if_result; // store expression result
|
||||
current_block->skip = ! if_result; //don't execute if the expresion result was not zero
|
||||
ib->if_expr_evaluated = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2537,7 +2543,7 @@ int parser_t::eval( const wcstring &cmdStr, const io_chain_t &io, enum block_typ
|
||||
|
||||
eval_level++;
|
||||
|
||||
this->push_block( block_type );
|
||||
this->push_block( new block_t(block_type) );
|
||||
|
||||
current_tokenizer = new tokenizer;
|
||||
tok_init( current_tokenizer, cmd, 0 );
|
||||
@ -3611,3 +3617,28 @@ int parser_t::test( const wchar_t * buff,
|
||||
|
||||
}
|
||||
|
||||
block_t::block_t(int t) :
|
||||
type(t),
|
||||
skip(),
|
||||
tok_pos(),
|
||||
had_command(),
|
||||
loop_status(),
|
||||
job(),
|
||||
function_data(),
|
||||
state1_ptr(),
|
||||
state2_ptr(),
|
||||
src_filename(),
|
||||
src_lineno(),
|
||||
wants_pop_env(false),
|
||||
event_blocks(),
|
||||
outer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
block_t::~block_t()
|
||||
{
|
||||
if (state1_ptr != NULL)
|
||||
delete state1_ptr;
|
||||
if (state2_ptr != NULL)
|
||||
delete state2_ptr;
|
||||
}
|
||||
|
148
parser.h
148
parser.h
@ -18,9 +18,9 @@
|
||||
#define PARSER_TEST_INCOMPLETE 2
|
||||
|
||||
/**
|
||||
event_block_t represents a block on events of the specified type
|
||||
event_blockage_t represents a block on events of the specified type
|
||||
*/
|
||||
struct event_block_t
|
||||
struct event_blockage_t
|
||||
{
|
||||
/**
|
||||
The types of events to block. This is interpreted as a bitset
|
||||
@ -33,10 +33,10 @@ struct event_block_t
|
||||
unsigned int typemask;
|
||||
};
|
||||
|
||||
typedef std::list<event_block_t> event_block_list_t;
|
||||
typedef std::list<event_blockage_t> event_blockage_list_t;
|
||||
|
||||
inline bool event_block_list_blocks_type(const event_block_list_t &ebls, int type) {
|
||||
for (event_block_list_t::const_iterator iter = ebls.begin(); iter != ebls.end(); ++iter) {
|
||||
inline bool event_block_list_blocks_type(const event_blockage_list_t &ebls, int type) {
|
||||
for (event_blockage_list_t::const_iterator iter = ebls.begin(); iter != ebls.end(); ++iter) {
|
||||
if( iter->typemask & (1<<EVENT_ANY ) )
|
||||
return true;
|
||||
if( iter->typemask & (1<<type) )
|
||||
@ -46,6 +46,28 @@ inline bool event_block_list_blocks_type(const event_block_list_t &ebls, int typ
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Types of blocks
|
||||
*/
|
||||
enum block_type_t
|
||||
{
|
||||
WHILE, /**< While loop block */
|
||||
FOR, /**< For loop block */
|
||||
IF, /**< If block */
|
||||
FUNCTION_DEF, /**< Function definition block */
|
||||
FUNCTION_CALL, /**< Function invocation block */
|
||||
FUNCTION_CALL_NO_SHADOW, /**< Function invocation block with no variable shadowing */
|
||||
SWITCH, /**< Switch block */
|
||||
FAKE, /**< Fake block */
|
||||
SUBST, /**< Command substitution scope */
|
||||
TOP, /**< Outermost block */
|
||||
BEGIN, /**< Unconditional block */
|
||||
SOURCE, /**< Block created by the . (source) builtin */
|
||||
EVENT, /**< Block created on event notifier invocation */
|
||||
BREAKPOINT, /**< Breakpoint block */
|
||||
}
|
||||
;
|
||||
|
||||
/** Block state template, to replace the discriminated union */
|
||||
struct block_state_base_t {
|
||||
public:
|
||||
@ -61,9 +83,9 @@ struct block_state_t : public block_state_base_t {
|
||||
/**
|
||||
block_t represents a block of commands.
|
||||
*/
|
||||
typedef struct block
|
||||
struct block_t
|
||||
{
|
||||
int type; /**< Type of block. Can be one of WHILE, FOR, IF and FUNCTION */
|
||||
int type; /**< Type of block. Can be one of WHILE, FOR, IF and FUNCTION, or FAKE */
|
||||
int skip; /**< Whether execution of the commands in this block should be skipped */
|
||||
int tok_pos; /**< The start index of the block */
|
||||
int had_command; /**< Set to non-zero once a command has been executed in this block */
|
||||
@ -100,7 +122,7 @@ typedef struct block
|
||||
block_state_base_t *state1_ptr;
|
||||
|
||||
template<typename T>
|
||||
T& state1(void) {
|
||||
T& state1_NOPE(void) {
|
||||
block_state_t<T> *state;
|
||||
if (state1_ptr == NULL) {
|
||||
state = new block_state_t<T>();
|
||||
@ -119,7 +141,7 @@ typedef struct block
|
||||
block_state_base_t *state2_ptr;
|
||||
|
||||
template<typename T>
|
||||
T& state2(void) {
|
||||
T& state2_NOPE(void) {
|
||||
block_state_t<T> *state;
|
||||
if (state2_ptr == NULL) {
|
||||
state = new block_state_t<T>();
|
||||
@ -145,44 +167,84 @@ typedef struct block
|
||||
bool wants_pop_env;
|
||||
|
||||
/** List of event blocks. */
|
||||
event_block_list_t event_blocks;
|
||||
event_blockage_list_t event_blocks;
|
||||
|
||||
/**
|
||||
Next outer block
|
||||
*/
|
||||
struct block *outer;
|
||||
block_t *outer;
|
||||
|
||||
/** Constructor */
|
||||
block_t(int t);
|
||||
|
||||
/** Destructor */
|
||||
~block()
|
||||
{
|
||||
if (state1_ptr != NULL)
|
||||
delete state1_ptr;
|
||||
if (state2_ptr != NULL)
|
||||
delete state2_ptr;
|
||||
}
|
||||
} block_t;
|
||||
virtual ~block_t();
|
||||
};
|
||||
|
||||
/**
|
||||
Types of blocks
|
||||
*/
|
||||
enum block_type_t
|
||||
{
|
||||
WHILE, /**< While loop block */
|
||||
FOR, /**< For loop block */
|
||||
IF, /**< If block */
|
||||
FUNCTION_DEF, /**< Function definition block */
|
||||
FUNCTION_CALL, /**< Function invocation block */
|
||||
FUNCTION_CALL_NO_SHADOW, /**< Function invocation block with no variable shadowing */
|
||||
SWITCH, /**< Switch block */
|
||||
FAKE, /**< Fake block */
|
||||
SUBST, /**< Command substitution scope */
|
||||
TOP, /**< Outermost block */
|
||||
BEGIN, /**< Unconditional block */
|
||||
SOURCE, /**< Block created by the . (source) builtin */
|
||||
EVENT, /**< Block created on event notifier invocation */
|
||||
BREAKPOINT, /**< Breakpoint block */
|
||||
}
|
||||
;
|
||||
struct if_block_t : public block_t {
|
||||
bool if_expr_evaluated; // whether the clause of the if statement has been tested
|
||||
bool if_expr_result; // if so, whether it evaluated to true
|
||||
bool else_evaluated; // whether we've encountered a terminal else block
|
||||
if_block_t() :
|
||||
if_expr_evaluated(false),
|
||||
if_expr_result(false),
|
||||
else_evaluated(false),
|
||||
block_t(IF)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct event_block_t : public block_t {
|
||||
const event_t * const event;
|
||||
event_block_t(const event_t *evt) : block_t(EVENT), event(evt)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct function_block_t : public block_t {
|
||||
process_t *process;
|
||||
wcstring name;
|
||||
|
||||
function_block_t(process_t *p, const wcstring &n, bool shadows) :
|
||||
process(p),
|
||||
name(n),
|
||||
block_t( shadows ? FUNCTION_CALL : FUNCTION_CALL_NO_SHADOW )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct source_block_t : public block_t {
|
||||
const wchar_t * const source_file;
|
||||
source_block_t(const wchar_t *src) : source_file(src), block_t(SOURCE)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct for_block_t : public block_t {
|
||||
wcstring variable; // the variable that will be assigned each value in the sequence
|
||||
wcstring_list_t sequence; // the sequence of values
|
||||
for_block_t(const wcstring &var) :
|
||||
variable(var),
|
||||
sequence(),
|
||||
block_t(FOR)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct while_block_t : public block_t {
|
||||
int status;
|
||||
while_block_t() : status(0), block_t(WHILE)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct switch_block_t : public block_t {
|
||||
bool switch_taken;
|
||||
const wcstring switch_value;
|
||||
switch_block_t(const wcstring &sv) : switch_taken(false), switch_value(sv), block_t(SWITCH)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Possible states for a loop
|
||||
@ -344,7 +406,7 @@ class parser_t {
|
||||
block_t *current_block;
|
||||
|
||||
/** Global event blocks */
|
||||
event_block_list_t global_event_blocks;
|
||||
event_blockage_list_t global_event_blocks;
|
||||
|
||||
/** Current block level io redirections */
|
||||
io_chain_t block_io;
|
||||
@ -411,8 +473,8 @@ class parser_t {
|
||||
/** Get the list of jobs */
|
||||
job_list_t &job_list() { return my_job_list; }
|
||||
|
||||
/** Create block of specified type */
|
||||
void push_block( int type);
|
||||
/** Pushes the block. pop_block will call delete on it. */
|
||||
void push_block( block_t *newv );
|
||||
|
||||
/** Remove the outermost block namespace */
|
||||
void pop_block();
|
||||
|
Loading…
x
Reference in New Issue
Block a user