Removed discriminated union from block_t type, allowing us to store wcstrings in it

This commit is contained in:
ridiculousfish 2012-02-07 17:06:45 -08:00
parent e8af86017a
commit a0a43046b3
12 changed files with 156 additions and 93 deletions

View file

@ -65,7 +65,7 @@
D0A0853813B3ACEE0099B651 /* env_universal_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = env_universal_common.cpp; sourceTree = "<group>"; };
D0A0853913B3ACEE0099B651 /* env_universal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = env_universal.cpp; sourceTree = "<group>"; };
D0A0853A13B3ACEE0099B651 /* env.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = env.cpp; sourceTree = "<group>"; };
D0A0853B13B3ACEE0099B651 /* event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = event.cpp; sourceTree = "<group>"; };
D0A0853B13B3ACEE0099B651 /* event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = event.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
D0A0853C13B3ACEE0099B651 /* exec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = exec.cpp; sourceTree = "<group>"; };
D0A0853D13B3ACEE0099B651 /* expand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = expand.cpp; sourceTree = "<group>"; };
D0A0853E13B3ACEE0099B651 /* fallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fallback.cpp; sourceTree = "<group>"; };
@ -90,7 +90,7 @@
D0A0855113B3ACEE0099B651 /* output.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = output.cpp; sourceTree = "<group>"; };
D0A0855213B3ACEE0099B651 /* parse_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse_util.cpp; sourceTree = "<group>"; };
D0A0855313B3ACEE0099B651 /* parser_keywords.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser_keywords.cpp; sourceTree = "<group>"; };
D0A0855413B3ACEE0099B651 /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cpp; sourceTree = "<group>"; };
D0A0855413B3ACEE0099B651 /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = parser.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
D0A0855513B3ACEE0099B651 /* path.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = path.cpp; sourceTree = "<group>"; };
D0A0855613B3ACEE0099B651 /* print_help.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = print_help.cpp; sourceTree = "<group>"; };
D0A0855713B3ACEE0099B651 /* proc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = proc.cpp; sourceTree = "<group>"; };

View file

@ -415,20 +415,13 @@ static void builtin_bind_list()
*/
static void builtin_bind_key_names( int all )
{
array_list_t lst;
int i;
al_init( &lst );
input_terminfo_get_names( &lst, !all );
for( i=0; i<al_get_count(&lst); i++ )
const wcstring_list_t names = input_terminfo_get_names(!all);
for( size_t i=0; i<names.size(); i++ )
{
wchar_t *seq = (wchar_t *)al_get( &lst, i );
const wcstring &name = names.at(i);
sb_printf( sb_out, L"%ls\n", seq );
sb_printf( sb_out, L"%ls\n", name.c_str() );
}
al_destroy( &lst );
}
/**
@ -1091,14 +1084,12 @@ static void functions_def( wchar_t *name, string_buffer_t *out )
const wchar_t *desc = function_get_desc( name );
const wchar_t *def = function_get_definition(name);
array_list_t ev;
event_t search;
int i;
search.function_name = name;
search.type = EVENT_ANY;
al_init( &ev );
std::vector<event_t *> ev;
event_get( &search, &ev );
sb_append( out,
@ -1119,9 +1110,9 @@ static void functions_def( wchar_t *name, string_buffer_t *out )
sb_append( out, L" --no-scope-shadowing", NULL );
}
for( i=0; i<al_get_count( &ev); i++ )
for( size_t i=0; i<ev.size(); i++ )
{
event_t *next = (event_t *)al_get( &ev, i );
event_t *next = ev.at(i);
switch( next->type )
{
case EVENT_SIGNAL:
@ -1163,13 +1154,12 @@ static void functions_def( wchar_t *name, string_buffer_t *out )
}
al_destroy( &ev );
wcstring_list_t named = function_get_named_arguments( name );
if( named.size() > 0 )
{
sb_printf( out, L" --argument" );
for( i=0; i<(int)named.size(); i++ )
for( size_t i=0; i < named.size(); i++ )
{
sb_printf( out, L" %ls", named.at(i).c_str() );
}
@ -2835,7 +2825,7 @@ static int builtin_source( parser_t &parser, wchar_t ** argv )
parser.push_block( SOURCE );
reader_push_current_filename( fn_intern );
parser.current_block->param1.source_dest = fn_intern;
parser.current_block->state1<const wchar_t *>() = fn_intern;
parse_util_set_argv( (argc>2)?(argv+2):(argv+1), wcstring_list_t());
@ -3173,21 +3163,19 @@ static int builtin_for( parser_t &parser, wchar_t **argv )
else
{
parser.push_block( FOR );
al_init( &parser.current_block->param2.for_vars);
int i;
const wcstring for_variable = argv[1];
parser.current_block->tok_pos = parser.get_pos();
parser.current_block->param1.for_variable = halloc_wcsdup( parser.current_block, argv[1] );
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-- )
{
al_push( &parser.current_block->param2.for_vars, halloc_wcsdup( parser.current_block, argv[ i ] ) );
}
halloc_register( parser.current_block, parser.current_block->param2.for_vars.arr );
for_vars.push_back(argv[i]);
if( argc > 3 )
{
env_set( parser.current_block->param1.for_variable, argv[3], ENV_LOCAL );
env_set( for_variable.c_str(), argv[3], ENV_LOCAL );
}
else
{
@ -3247,7 +3235,7 @@ 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->param1.while_state = WHILE_TEST_AGAIN;
parser.current_block->state1<int>() = WHILE_TEST_AGAIN;
}
break;
@ -3267,15 +3255,18 @@ 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>();
if( parser.current_block->loop_status == LOOP_BREAK )
{
al_truncate( &parser.current_block->param2.for_vars, 0 );
for_vars.clear();
}
if( al_get_count( &parser.current_block->param2.for_vars ) )
if( ! for_vars.empty() )
{
wchar_t *val = (wchar_t *)al_pop( &parser.current_block->param2.for_vars );
env_set( parser.current_block->param1.for_variable, val, ENV_LOCAL);
const wcstring val = for_vars.back();
for_vars.pop_back();
const wcstring for_variable = parser.current_block->state1<wcstring>();
env_set( for_variable.c_str(), val.c_str(), ENV_LOCAL);
parser.current_block->loop_status = LOOP_NORMAL;
parser.current_block->skip = 0;
@ -3336,7 +3327,7 @@ static int builtin_else( parser_t &parser, wchar_t **argv )
{
if( parser.current_block == 0 ||
parser.current_block->type != IF ||
parser.current_block->param1.if_state != 1)
parser.current_block->state1<int>() != 1)
{
sb_printf( sb_err,
_( L"%ls: Not inside of 'if' block\n" ),
@ -3346,7 +3337,8 @@ static int builtin_else( parser_t &parser, wchar_t **argv )
}
else
{
parser.current_block->param1.if_state++;
int &if_state = parser.current_block->state1<int>();
if_state++;
parser.current_block->skip = !parser.current_block->skip;
env_pop();
env_push(0);
@ -3517,9 +3509,9 @@ static int builtin_switch( parser_t &parser, wchar_t **argv )
else
{
parser.push_block( SWITCH );
parser.current_block->param1.switch_value = halloc_wcsdup( parser.current_block, argv[1]);
parser.current_block->state1<wcstring>() = argv[1];
parser.current_block->skip=1;
parser.current_block->param2.switch_taken=0;
parser.current_block->state2<int>() = 0;
}
return res;
@ -3546,7 +3538,7 @@ static int builtin_case( parser_t &parser, wchar_t **argv )
parser.current_block->skip = 1;
if( parser.current_block->param2.switch_taken )
if( parser.current_block->state2<int>() )
{
return STATUS_BUILTIN_OK;
}
@ -3556,13 +3548,14 @@ static int builtin_case( parser_t &parser, wchar_t **argv )
int match;
unescaped = parse_util_unescape_wildcards( argv[i] );
match = wildcard_match( parser.current_block->param1.switch_value, unescaped );
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->param2.switch_taken = 1;
parser.current_block->state2<int>() = 1;
break;
}
}

View file

@ -822,10 +822,6 @@ static int builtin_set( parser_t &parser, wchar_t **argv )
std::vector<long> indexes;
wcstring_list_t result;
// al_init(&values);
// al_init(&indexes);
// al_init(&result);
const env_var_t dest_str = env_get_string(dest);
if (! dest_str.missing())
tokenize_variable_array2( dest_str, result );

View file

@ -336,7 +336,7 @@ void event_remove( event_t *criterion )
events.swap(new_list);
}
int event_get( event_t *criterion, array_list_t *out )
int event_get( event_t *criterion, std::vector<event_t *> *out )
{
size_t i;
int found = 0;
@ -353,7 +353,7 @@ int event_get( event_t *criterion, array_list_t *out )
{
found++;
if( out )
al_push( out, n );
out->push_back(n);
}
}
return found;
@ -461,7 +461,7 @@ static void event_fire_internal( event_t *event )
prev_status = proc_get_last_status();
parser_t &parser = parser_t::principal_parser();
parser.push_block( EVENT );
parser.current_block->param1.event = event;
parser.current_block->state1<event_t *>() = event;
parser.eval( buffer.c_str(), 0, TOP );
parser.pop_block();
proc_pop_interactive();

View file

@ -121,7 +121,7 @@ void event_remove( event_t *event );
\return the number of found matches
*/
int event_get( event_t *criterion, array_list_t *out );
int event_get( event_t *criterion, std::vector<event_t *> *out );
/**
Fire the specified event. The function_name field of the event must

View file

@ -1196,8 +1196,8 @@ void exec( parser_t &parser, job_t *j )
}
parser.push_block( shadows?FUNCTION_CALL:FUNCTION_CALL_NO_SHADOW );
parser.current_block->param2.function_call_process = p;
parser.current_block->param1.function_call_name = (wchar_t *)halloc_register( parser.current_block, wcsdup( p->argv0() ) );
parser.current_block->state2<process_t *>() = p;
parser.current_block->state1<wcstring>() = p->argv0();
/*

View file

@ -816,14 +816,14 @@ bool input_terminfo_get_name( const wcstring &seq, wcstring &name )
return false;
}
void input_terminfo_get_names( array_list_t *lst, int skip_null )
wcstring_list_t input_terminfo_get_names( bool skip_null )
{
int i;
CHECK( lst, );
wcstring_list_t result;
result.reserve(al_get_count(terminfo_mappings));
input_init();
for( i=0; i<al_get_count( terminfo_mappings ); i++ )
for( int i=0; i<al_get_count( terminfo_mappings ); i++ )
{
terminfo_mapping_t *m = (terminfo_mapping_t *)al_get( terminfo_mappings, i );
@ -831,8 +831,9 @@ void input_terminfo_get_names( array_list_t *lst, int skip_null )
{
continue;
}
al_push( lst, m->name );
result.push_back(wcstring(m->name));
}
return result;
}
wcstring_list_t input_function_get_names( void )

View file

@ -124,10 +124,8 @@ const wchar_t *input_terminfo_get_sequence( const wchar_t *name );
*/
bool input_terminfo_get_name( const wcstring &seq, wcstring &name );
/**
Return a list of all known terminfo names
*/
void input_terminfo_get_names( array_list_t *lst, int skip_null );
/** Return a list of all known terminfo names */
wcstring_list_t input_terminfo_get_names( bool skip_null );
/**

View file

@ -396,7 +396,11 @@ static int block_count( block_t *b )
void parser_t::push_block( int type )
{
block_t *newv = (block_t *)halloc( 0, sizeof( block_t ));
// block_t zerod = {};
// block_t *newv = new block_t(zerod);
void *buffer = halloc( 0, sizeof( block_t ));
bzero(buffer, sizeof(block_t));
block_t *newv = new(buffer) block_t();
newv->src_lineno = parser_t::get_lineno();
newv->src_filename = parser_t::current_filename()?intern(parser_t::current_filename()):0;
@ -437,7 +441,7 @@ void parser_t::push_block( int type )
(newv->type != TOP) )
{
env_push( type == FUNCTION_CALL );
halloc_register_function_void( current_block, &env_pop );
newv->wants_pop_env = true;
}
}
@ -454,7 +458,12 @@ void parser_t::pop_block()
}
current_block = current_block->outer;
halloc_free( old );
if (old->wants_pop_env)
env_pop();
old->~block_t();
halloc_free(old);
}
const wchar_t *parser_t::get_block_desc( int block ) const
@ -873,7 +882,7 @@ void parser_t::stack_trace( block_t *b, string_buffer_t *buff)
/*
This is an event handler
*/
sb_printf( buff, _(L"in event handler: %ls\n"), event_get_desc( b->param1.event ));
sb_printf( buff, _(L"in event handler: %ls\n"), event_get_desc( b->state1<event_t *>() ));
sb_printf( buff,
L"\n" );
@ -900,12 +909,14 @@ void parser_t::stack_trace( block_t *b, string_buffer_t *buff)
{
case SOURCE:
{
sb_printf( buff, _(L"in . (source) call of file '%ls',\n"), b->param1.source_dest );
const wcstring &source_dest = b->state1<wcstring>();
sb_printf( buff, _(L"in . (source) call of file '%ls',\n"), source_dest.c_str() );
break;
}
case FUNCTION_CALL:
{
sb_printf( buff, _(L"in function '%ls',\n"), b->param1.function_call_name );
const wcstring &function_call_name = b->state1<wcstring>();
sb_printf( buff, _(L"in function '%ls',\n"), function_call_name.c_str() );
break;
}
case SUBST:
@ -932,14 +943,15 @@ void parser_t::stack_trace( block_t *b, string_buffer_t *buff)
if( b->type == FUNCTION_CALL )
{
if( b->param2.function_call_process->argv(1) )
const process_t * const process = b->state2<process_t*>();
if( process->argv(1) )
{
string_buffer_t tmp;
sb_init( &tmp );
for( i=1; b->param2.function_call_process->argv(i); i++ )
for( i=1; process->argv(i); i++ )
{
sb_append( &tmp, i>1?L" ":L"", b->param2.function_call_process->argv(i), NULL );
sb_append( &tmp, i>1?L" ":L"", process->argv(i), NULL );
}
sb_printf( buff, _(L"\twith parameter list '%ls'\n"), (wchar_t *)tmp.buff );
@ -965,16 +977,21 @@ void parser_t::stack_trace( block_t *b, string_buffer_t *buff)
*/
const wchar_t *parser_t::is_function() const
{
// PCA: Have to make this a string somehow
ASSERT_IS_MAIN_THREAD();
wcstring result;
block_t *b = current_block;
while( 1 )
{
if( !b )
{
return 0;
return NULL;
}
if( b->type == FUNCTION_CALL )
{
return b->param1.function_call_name;
result = b->state1<wcstring>();
return result.c_str();
}
b=b->outer;
}
@ -1026,7 +1043,8 @@ const wchar_t *parser_t::current_filename() const
}
if( b->type == FUNCTION_CALL )
{
return function_get_definition_file(b->param1.function_call_name );
wcstring function_call_name = b->state1<wcstring>();
return function_get_definition_file(function_call_name.c_str());
}
b=b->outer;
}
@ -1784,9 +1802,9 @@ int parser_t::parse_job( process_t *p,
{
new_block = 1;
}
else if( current_block->param1.while_state == WHILE_TEST_AGAIN )
else if( current_block->state1<int>() == WHILE_TEST_AGAIN )
{
current_block->param1.while_state = WHILE_TEST_FIRST;
current_block->state1<int>() = WHILE_TEST_FIRST;
}
else
{
@ -1796,7 +1814,7 @@ int parser_t::parse_job( process_t *p,
if( new_block )
{
this->push_block( WHILE );
current_block->param1.while_state=WHILE_TEST_FIRST;
current_block->state1<int>() = WHILE_TEST_FIRST;
current_block->tok_pos = mark;
}
@ -1810,7 +1828,7 @@ int parser_t::parse_job( process_t *p,
this->push_block( IF );
current_block->param1.if_state=0;
current_block->state1<int>()=0;
current_block->tok_pos = mark;
is_new_block=1;
@ -2193,7 +2211,7 @@ void parser_t::skipped_exec( job_t * j )
else if( wcscmp( p->argv0(), L"else" )==0)
{
if( (current_block->type == IF ) &&
(current_block->param1.if_state != 0))
(current_block->state1<int>() != 0))
{
exec( *this, j );
return;
@ -2328,12 +2346,12 @@ void parser_t::eval_job( tokenizer *tok )
if( current_block->type == WHILE )
{
switch( current_block->param1.while_state )
switch( current_block->state1<int>() )
{
case WHILE_TEST_FIRST:
{
current_block->skip = proc_get_last_status()!= 0;
current_block->param1.while_state=WHILE_TESTED;
current_block->state1<int>()=WHILE_TESTED;
}
break;
}
@ -2341,11 +2359,11 @@ void parser_t::eval_job( tokenizer *tok )
if( current_block->type == IF )
{
if( (!current_block->param1.if_state) &&
if( (!current_block->state1<int>()) &&
(!current_block->skip) )
{
current_block->skip = proc_get_last_status()!= 0;
current_block->param1.if_state++;
current_block->state1<int>()++;
}
}

View file

@ -35,10 +35,20 @@ typedef struct event_block
The next event_block struct
*/
struct event_block *next;
}
event_block_t;
} event_block_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.
@ -65,9 +75,7 @@ typedef struct block
*/
void *data;
/**
First block type specific variable
*/
#if 0
union
{
int while_state; /**< True if the loop condition has not yet been evaluated*/
@ -78,7 +86,42 @@ typedef struct block
event_t *event; /**<The event that triggered this block */
wchar_t *function_call_name;
} param1;
#endif
/** First block type specific variable */
block_state_base_t *state1_ptr;
template<typename T>
T& state1(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);
assert(state != NULL);
}
return state->value;
}
/** Second block type specific variable */
block_state_base_t *state2_ptr;
template<typename T>
T& state2(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;
}
#if 0
/**
Second block type specific variable
*/
@ -88,6 +131,7 @@ typedef struct block
int switch_taken; /**< Whether a switch match has already been found */
process_t *function_call_process; /**< The process representing this function call */
} param2;
#endif
/**
@ -99,6 +143,9 @@ typedef struct block
Line number where this block was created
*/
int src_lineno;
/** Whether we should pop the environment variable stack when we're popped */
bool wants_pop_env;
/**
Some naming confusion. This is a pointer to the first element in the list of all event blocks.
@ -108,7 +155,16 @@ typedef struct block
/**
Next outer block
*/
struct block *outer;
struct block *outer;
/** Destructor */
~block()
{
if (state1_ptr != NULL)
delete state1_ptr;
if (state2_ptr != NULL)
delete state2_ptr;
}
} block_t;
/**
@ -278,7 +334,7 @@ class parser_t {
/** Create a parser of the given type */
parser_t(enum parser_type_t type);
/** The current innermost block */
/** The current innermost block, allocated with new */
block_t *current_block;
/** Global event blocks */

View file

@ -153,10 +153,12 @@ int wildcard_has( const wchar_t *str, int internal )
\param wc The wildcard.
\param is_first Whether files beginning with dots should not be matched against wildcards.
*/
static int wildcard_match2( const wchar_t *str,
const wchar_t *wc,
static int wildcard_match2( const wcstring &str_str,
const wcstring &wc_str,
int is_first )
{
const wchar_t *str = str_str.c_str();
const wchar_t *wc = wc_str.c_str();
if( *str == 0 && *wc==0 )
return 1;
@ -329,7 +331,7 @@ int wildcard_complete( const wchar_t *str,
}
int wildcard_match( const wchar_t *str, const wchar_t *wc )
int wildcard_match( const wcstring &str, const wcstring &wc )
{
return wildcard_match2( str, wc, 1 );
}

View file

@ -79,8 +79,7 @@ int wildcard_expand_string(const wcstring &wc, const wcstring &base_dir, int fla
\param wc The wildcard to test against
\return true if the wildcard matched
*/
int wildcard_match( const wchar_t *str,
const wchar_t *wc );
int wildcard_match( const wcstring &str, const wcstring &wc );
/**