aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--builtin.cpp50
-rw-r--r--parser.cpp132
-rw-r--r--parser.h126
-rw-r--r--reader.cpp2
4 files changed, 168 insertions, 142 deletions
diff --git a/builtin.cpp b/builtin.cpp
index 362b01ed..f20e1f12 100644
--- a/builtin.cpp
+++ b/builtin.cpp
@@ -842,8 +842,8 @@ static int builtin_block( parser_t &parser, wchar_t **argv )
case UNSET:
{
while( block &&
- block->type != FUNCTION_CALL &&
- block->type != FUNCTION_CALL_NO_SHADOW )
+ block->type() != FUNCTION_CALL &&
+ block->type() != FUNCTION_CALL_NO_SHADOW )
block = block->outer;
}
}
@@ -1530,8 +1530,7 @@ static int builtin_function( parser_t &parser, wchar_t **argv )
woptind=0;
- block_t *newv = new block_t(FUNCTION_DEF);
- parser.push_block( newv );
+ parser.push_block( new function_def_block_t() );
static const struct woption
long_options[] =
@@ -1663,7 +1662,7 @@ static int builtin_function( parser_t &parser, wchar_t **argv )
{
block_t *b = parser.current_block;
- while( b && (b->type != SUBST) )
+ while( b && (b->type() != SUBST) )
b = b->outer;
if( b )
@@ -1730,7 +1729,7 @@ static int builtin_function( parser_t &parser, wchar_t **argv )
case 'h':
parser.pop_block();
- parser.push_block( new block_t(FAKE) );
+ parser.push_block( new fake_block_t() );
builtin_print_help( parser, argv[0], stdout_buffer );
return STATUS_BUILTIN_OK;
@@ -1835,7 +1834,7 @@ static int builtin_function( parser_t &parser, wchar_t **argv )
stderr_buffer.push_back(L'\n');
parser.pop_block();
- parser.push_block( new block_t(FAKE) );
+ parser.push_block( new fake_block_t() );
}
else
{
@@ -3204,7 +3203,7 @@ static int builtin_for( parser_t &parser, wchar_t **argv )
if( res )
{
- parser.push_block( new block_t(FAKE) );
+ parser.push_block( new fake_block_t() );
}
else
{
@@ -3235,7 +3234,7 @@ static int builtin_for( parser_t &parser, wchar_t **argv )
*/
static int builtin_begin( parser_t &parser, wchar_t **argv )
{
- parser.push_block( new block_t(BEGIN) );
+ parser.push_block( new scope_block_t(BEGIN) );
parser.current_block->tok_pos = parser.get_pos();
return proc_get_last_status();
}
@@ -3266,7 +3265,7 @@ static int builtin_end( parser_t &parser, wchar_t **argv )
*/
int kill_block = 1;
- switch( parser.current_block->type )
+ switch( parser.current_block->type() )
{
case WHILE:
{
@@ -3290,6 +3289,7 @@ static int builtin_end( parser_t &parser, wchar_t **argv )
case IF:
case SUBST:
case BEGIN:
+ case SWITCH:
/*
Nothing special happens at the end of these commands. The scope just ends.
*/
@@ -3364,6 +3364,10 @@ static int builtin_end( parser_t &parser, wchar_t **argv )
}
break;
+
+ default:
+ assert(false); //should never get here
+ break;
}
if( kill_block )
@@ -3385,7 +3389,7 @@ 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 (if_block->if_expr_evaluated && ! if_block->else_evaluated)
@@ -3441,8 +3445,8 @@ static int builtin_break_continue( parser_t &parser, wchar_t **argv )
while( (b != 0) &&
- ( b->type != WHILE) &&
- (b->type != FOR ) )
+ ( b->type() != WHILE) &&
+ (b->type() != FOR ) )
{
b = b->outer;
}
@@ -3457,8 +3461,8 @@ static int builtin_break_continue( parser_t &parser, wchar_t **argv )
}
b = parser.current_block;
- while( ( b->type != WHILE) &&
- (b->type != FOR ) )
+ while( ( b->type() != WHILE) &&
+ (b->type() != FOR ) )
{
b->skip=1;
b = b->outer;
@@ -3475,7 +3479,7 @@ static int builtin_break_continue( parser_t &parser, wchar_t **argv )
static int builtin_breakpoint( parser_t &parser, wchar_t **argv )
{
- parser.push_block( new block_t(BREAKPOINT) );
+ parser.push_block( new breakpoint_block_t() );
reader_read( STDIN_FILENO, real_io ? *real_io : io_chain_t() );
@@ -3525,8 +3529,8 @@ static int builtin_return( parser_t &parser, wchar_t **argv )
while( (b != 0) &&
- ( b->type != FUNCTION_CALL &&
- b->type != FUNCTION_CALL_NO_SHADOW) )
+ ( b->type() != FUNCTION_CALL &&
+ b->type() != FUNCTION_CALL_NO_SHADOW) )
{
b = b->outer;
}
@@ -3541,10 +3545,10 @@ static int builtin_return( parser_t &parser, wchar_t **argv )
}
b = parser.current_block;
- while( ( b->type != FUNCTION_CALL &&
- b->type != FUNCTION_CALL_NO_SHADOW ) )
+ while( ( b->type() != FUNCTION_CALL &&
+ b->type() != FUNCTION_CALL_NO_SHADOW ) )
{
- b->type = FAKE;
+ b->mark_as_fake();
b->skip=1;
b = b->outer;
}
@@ -3571,7 +3575,7 @@ static int builtin_switch( parser_t &parser, wchar_t **argv )
builtin_print_help( parser, argv[0], stderr_buffer );
res=1;
- parser.push_block( new block_t(FAKE) );
+ parser.push_block( new fake_block_t() );
}
else
{
@@ -3593,7 +3597,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" ),
diff --git a/parser.cpp b/parser.cpp
index c55c8334..bc1d6961 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -422,13 +422,13 @@ static int block_count( block_t *b )
void parser_t::push_block( block_t *newv )
{
- const int type = newv->type;
+ const enum block_type_t 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;
if (current_block && current_block->skip)
- newv->type = FAKE;
+ newv->mark_as_fake();
/*
New blocks should be skipped if the outer block is skipped,
@@ -458,9 +458,9 @@ void parser_t::push_block( block_t *newv )
current_block = newv;
- if( (newv->type != FUNCTION_DEF) &&
- (newv->type != FAKE) &&
- (newv->type != TOP) )
+ if( (newv->type() != FUNCTION_DEF) &&
+ (newv->type() != FAKE) &&
+ (newv->type() != TOP) )
{
env_push( type == FUNCTION_CALL );
newv->wants_pop_env = true;
@@ -887,7 +887,7 @@ void parser_t::stack_trace( block_t *b, wcstring &buff)
if( !b )
return;
- if( b->type==EVENT )
+ if( b->type()==EVENT )
{
/*
This is an event handler
@@ -908,7 +908,7 @@ void parser_t::stack_trace( block_t *b, wcstring &buff)
return;
}
- if( b->type == FUNCTION_CALL || b->type==SOURCE || b->type==SUBST)
+ if( b->type() == FUNCTION_CALL || b->type()==SOURCE || b->type()==SUBST)
{
/*
These types of blocks should be printed
@@ -916,7 +916,7 @@ void parser_t::stack_trace( block_t *b, wcstring &buff)
int i;
- switch( b->type)
+ switch( b->type())
{
case SOURCE:
{
@@ -936,6 +936,9 @@ void parser_t::stack_trace( block_t *b, wcstring &buff)
append_format( buff, _(L"in command substitution\n") );
break;
}
+
+ default: /* Can't get here */
+ break;
}
const wchar_t *file = b->src_filename;
@@ -953,7 +956,7 @@ void parser_t::stack_trace( block_t *b, wcstring &buff)
_(L"\tcalled on standard input,\n") );
}
- if( b->type == FUNCTION_CALL )
+ if( b->type() == FUNCTION_CALL )
{
const function_block_t *fb = static_cast<const function_block_t *>(b);
const process_t * const process = fb->process;
@@ -999,7 +1002,7 @@ const wchar_t *parser_t::is_function() const
{
return NULL;
}
- if( b->type == FUNCTION_CALL )
+ if( b->type() == FUNCTION_CALL )
{
const function_block_t *fb = static_cast<const function_block_t *>(b);
return fb->name.c_str();
@@ -1051,7 +1054,7 @@ const wchar_t *parser_t::current_filename() const
{
return reader_current_filename();
}
- if( b->type == FUNCTION_CALL )
+ if( b->type() == FUNCTION_CALL )
{
const function_block_t *fb = static_cast<const function_block_t *>(b);
return function_get_definition_file(fb->name);
@@ -1403,7 +1406,7 @@ void parser_t::parse_job_argument_list( process_t *p,
But if this is in fact a case statement, then it should be evaluated
*/
- if( (current_block->type == SWITCH) && args.at(0).completion == L"case" && p->type == INTERNAL_BUILTIN )
+ if( (current_block->type() == SWITCH) && args.at(0).completion == L"case" && p->type == INTERNAL_BUILTIN )
{
skip=0;
}
@@ -1855,7 +1858,7 @@ int parser_t::parse_job( process_t *p,
tok_next( tok );
while_block_t *wb = NULL;
- if( ( current_block->type != WHILE ) )
+ if( ( current_block->type() != WHILE ) )
{
new_block = true;
}
@@ -1917,9 +1920,9 @@ int parser_t::parse_job( process_t *p,
block scopes are pushed on function invocation changes,
then this check will break.
*/
- if( ( current_block->type == TOP ) &&
+ if( ( current_block->type() == TOP ) &&
( current_block->outer ) &&
- ( current_block->outer->type == FUNCTION_CALL ) )
+ ( current_block->outer->type() == FUNCTION_CALL ) )
is_function_call = 1;
/*
@@ -2210,7 +2213,7 @@ int parser_t::parse_job( process_t *p,
{
if( !is_new_block )
{
- current_block->had_command = 1;
+ current_block->had_command = true;
}
}
@@ -2249,7 +2252,7 @@ void parser_t::skipped_exec( job_t * j )
( wcscmp( p->argv0(), L"begin" )==0) ||
( wcscmp( p->argv0(), L"function" )==0))
{
- this->push_block( new block_t(FAKE) );
+ this->push_block( new fake_block_t() );
}
else if( wcscmp( p->argv0(), L"end" )==0)
{
@@ -2262,7 +2265,7 @@ void parser_t::skipped_exec( job_t * j )
}
else if( wcscmp( p->argv0(), L"else" )==0)
{
- if( (current_block->type == IF ) &&
+ if( (current_block->type() == IF ) &&
(static_cast<const if_block_t*>(current_block)->if_expr_evaluated))
{
exec( *this, j );
@@ -2271,7 +2274,7 @@ void parser_t::skipped_exec( job_t * j )
}
else if( wcscmp( p->argv0(), L"case" )==0)
{
- if(current_block->type == SWITCH)
+ if(current_block->type() == SWITCH)
{
exec( *this, j );
return;
@@ -2395,7 +2398,7 @@ void parser_t::eval_job( tokenizer *tok )
profile_item->exec=(int)(t3-t2);
}
- if( current_block->type == WHILE )
+ if( current_block->type() == WHILE )
{
while_block_t *wb = static_cast<while_block_t *>(current_block);
switch( wb->status )
@@ -2411,7 +2414,7 @@ void parser_t::eval_job( tokenizer *tok )
}
}
- if( current_block->type == IF )
+ if( current_block->type() == IF )
{
if_block_t *ib = static_cast<if_block_t *>(current_block);
if( (! ib->if_expr_evaluated) &&
@@ -2543,7 +2546,7 @@ int parser_t::eval( const wcstring &cmdStr, const io_chain_t &io, enum block_typ
eval_level++;
- this->push_block( new block_t(block_type) );
+ this->push_block( new scope_block_t(block_type) );
current_tokenizer = new tokenizer;
tok_init( current_tokenizer, cmd, 0 );
@@ -2580,7 +2583,7 @@ int parser_t::eval( const wcstring &cmdStr, const io_chain_t &io, enum block_typ
//debug( 2, L"Status %d\n", proc_get_last_status() );
debug( 1,
- L"%ls", parser_t::get_block_desc( current_block->type ) );
+ L"%ls", parser_t::get_block_desc( current_block->type() ) );
debug( 1,
BLOCK_END_ERR_MSG );
fwprintf( stderr, L"%ls", parser_t::current_line() );
@@ -3617,16 +3620,15 @@ int parser_t::test( const wchar_t * buff,
}
-block_t::block_t(int t) :
- type(t),
+block_t::block_t(block_type_t t) :
+ block_type(t),
+ made_fake(false),
skip(),
- tok_pos(),
had_command(),
+ tok_pos(),
loop_status(),
job(),
function_data(),
- state1_ptr(),
- state2_ptr(),
src_filename(),
src_lineno(),
wants_pop_env(false),
@@ -3637,8 +3639,74 @@ block_t::block_t(int t) :
block_t::~block_t()
{
- if (state1_ptr != NULL)
- delete state1_ptr;
- if (state2_ptr != NULL)
- delete state2_ptr;
+}
+
+/* Various block constructors */
+
+if_block_t::if_block_t() :
+ if_expr_evaluated(false),
+ if_expr_result(false),
+ else_evaluated(false),
+ block_t(IF)
+{
+}
+
+event_block_t::event_block_t(const event_t *evt) :
+ block_t(EVENT),
+ event(evt)
+{
+}
+
+function_block_t::function_block_t(process_t *p, const wcstring &n, bool shadows) :
+ process(p),
+ name(n),
+ block_t( shadows ? FUNCTION_CALL : FUNCTION_CALL_NO_SHADOW )
+{
+}
+
+source_block_t::source_block_t(const wchar_t *src) :
+ source_file(src),
+ block_t(SOURCE)
+{
+}
+
+for_block_t::for_block_t(const wcstring &var) :
+ variable(var),
+ sequence(),
+ block_t(FOR)
+{
+}
+
+while_block_t::while_block_t() :
+ status(0),
+ block_t(WHILE)
+{
+}
+
+switch_block_t::switch_block_t(const wcstring &sv) :
+ switch_taken(false),
+ switch_value(sv),
+ block_t(SWITCH)
+{
+}
+
+fake_block_t::fake_block_t() :
+ block_t(FAKE)
+{
+}
+
+function_def_block_t::function_def_block_t() :
+ block_t(FUNCTION_DEF)
+{
+}
+
+scope_block_t::scope_block_t(block_type_t type) :
+ block_t(type)
+{
+ assert(type == BEGIN || type == TOP || type == SUBST);
+}
+
+breakpoint_block_t::breakpoint_block_t() :
+ block_t(BREAKPOINT)
+{
}
diff --git a/parser.h b/parser.h
index d968ea20..6e00adcf 100644
--- a/parser.h
+++ b/parser.h
@@ -68,27 +68,28 @@ enum block_type_t
}
;
-/** Block state template, to replace the discriminated union */
-struct block_state_base_t {
- public:
- virtual ~block_state_base_t() {}
-};
-
-template<typename T>
-struct block_state_t : public block_state_base_t {
- T value;
- block_state_t() : value() {}
-};
-
/**
block_t represents a block of commands.
*/
struct block_t
{
- 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 */
+ protected:
+ /** Protected constructor. Use one of the subclasses below. */
+ block_t(block_type_t t);
+
+ private:
+ const block_type_t block_type; /**< Type of block. */
+ bool made_fake;
+
+ public:
+ block_type_t type() const { return this->made_fake ? FAKE : this->block_type; }
+
+ /** Mark a block as fake; this is used by the return statement. */
+ void mark_as_fake() { this->made_fake = true; }
+
+ bool skip; /**< Whether execution of the commands in this block should be skipped */
+ bool had_command; /**< Set to non-zero once a command has been executed in this block */
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 */
/**
Status for the current loop block. Can be any of the values from the loop_status enum.
@@ -118,41 +119,6 @@ struct block_t
} param1;
#endif
- /** First block type specific variable */
- block_state_base_t *state1_ptr;
-
- template<typename T>
- T& state1_NOPE(void) {
- block_state_t<T> *state;
- if (state1_ptr == NULL) {
- state = new block_state_t<T>();
- state1_ptr = state;
- } else {
- state = dynamic_cast<block_state_t<T> *>(state1_ptr);
- if (state == NULL) {
- printf("Expected type %s, but instead got type %s\n", typeid(T).name(), typeid(*state1_ptr).name());
- abort();
- }
- }
- return state->value;
- }
-
- /** Second block type specific variable */
- block_state_base_t *state2_ptr;
-
- template<typename T>
- T& state2_NOPE(void) {
- block_state_t<T> *state;
- if (state2_ptr == NULL) {
- state = new block_state_t<T>();
- state2_ptr = state;
- } else {
- state = dynamic_cast<block_state_t<T> *>(state2_ptr);
- assert(state != NULL);
- }
- return state->value;
- }
-
/**
Name of file that created this block
*/
@@ -173,10 +139,7 @@ struct block_t
Next outer block
*/
block_t *outer;
-
- /** Constructor */
- block_t(int t);
-
+
/** Destructor */
virtual ~block_t();
};
@@ -185,65 +148,56 @@ 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)
- {
- }
+ if_block_t();
};
struct event_block_t : public block_t {
const event_t * const event;
- event_block_t(const event_t *evt) : block_t(EVENT), event(evt)
- {
- }
+ event_block_t(const event_t *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 )
- {
- }
+ function_block_t(process_t *p, const wcstring &n, bool shadows);
};
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)
- {
- }
+ source_block_t(const wchar_t *src);
};
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)
- {
- }
+ for_block_t(const wcstring &var);
};
struct while_block_t : public block_t {
int status;
- while_block_t() : status(0), block_t(WHILE)
- {
- }
+ while_block_t();
};
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)
- {
- }
+ switch_block_t(const wcstring &sv);
+};
+
+struct fake_block_t : public block_t {
+ fake_block_t();
+};
+
+struct function_def_block_t : public block_t {
+ function_def_block_t();
+};
+
+struct scope_block_t : public block_t {
+ scope_block_t(block_type_t type); //must be BEGIN, TOP or SUBST
+};
+
+struct breakpoint_block_t : public block_t {
+ breakpoint_block_t();
};
/**
diff --git a/reader.cpp b/reader.cpp
index a245d1c3..4445d088 100644
--- a/reader.cpp
+++ b/reader.cpp
@@ -2390,7 +2390,7 @@ static void handle_end_loop()
b;
b = b->outer )
{
- if( b->type == BREAKPOINT )
+ if( b->type() == BREAKPOINT )
{
is_breakpoint = 1;
break;