From a0a43046b3b21853fdec115dd35f1def9c312670 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Tue, 7 Feb 2012 17:06:45 -0800 Subject: [PATCH] Removed discriminated union from block_t type, allowing us to store wcstrings in it --- FishsFish.xcodeproj/project.pbxproj | 4 +- builtin.cpp | 69 +++++++++++++--------------- builtin_set.cpp | 4 -- event.cpp | 6 +-- event.h | 2 +- exec.cpp | 4 +- input.cpp | 13 +++--- input.h | 6 +-- parser.cpp | 60 ++++++++++++++++--------- parser.h | 70 ++++++++++++++++++++++++++--- wildcard.cpp | 8 ++-- wildcard.h | 3 +- 12 files changed, 156 insertions(+), 93 deletions(-) diff --git a/FishsFish.xcodeproj/project.pbxproj b/FishsFish.xcodeproj/project.pbxproj index 0f8859be8..43f764d09 100644 --- a/FishsFish.xcodeproj/project.pbxproj +++ b/FishsFish.xcodeproj/project.pbxproj @@ -65,7 +65,7 @@ D0A0853813B3ACEE0099B651 /* env_universal_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = env_universal_common.cpp; sourceTree = ""; }; D0A0853913B3ACEE0099B651 /* env_universal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = env_universal.cpp; sourceTree = ""; }; D0A0853A13B3ACEE0099B651 /* env.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = env.cpp; sourceTree = ""; }; - D0A0853B13B3ACEE0099B651 /* event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = event.cpp; sourceTree = ""; }; + D0A0853B13B3ACEE0099B651 /* event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = event.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; D0A0853C13B3ACEE0099B651 /* exec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = exec.cpp; sourceTree = ""; }; D0A0853D13B3ACEE0099B651 /* expand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = expand.cpp; sourceTree = ""; }; D0A0853E13B3ACEE0099B651 /* fallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fallback.cpp; sourceTree = ""; }; @@ -90,7 +90,7 @@ D0A0855113B3ACEE0099B651 /* output.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = output.cpp; sourceTree = ""; }; D0A0855213B3ACEE0099B651 /* parse_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parse_util.cpp; sourceTree = ""; }; D0A0855313B3ACEE0099B651 /* parser_keywords.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser_keywords.cpp; sourceTree = ""; }; - D0A0855413B3ACEE0099B651 /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cpp; sourceTree = ""; }; + D0A0855413B3ACEE0099B651 /* parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = parser.cpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; D0A0855513B3ACEE0099B651 /* path.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = path.cpp; sourceTree = ""; }; D0A0855613B3ACEE0099B651 /* print_help.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = print_help.cpp; sourceTree = ""; }; D0A0855713B3ACEE0099B651 /* proc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = proc.cpp; sourceTree = ""; }; diff --git a/builtin.cpp b/builtin.cpp index 9a3b4776b..dbc301653 100644 --- a/builtin.cpp +++ b/builtin.cpp @@ -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 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; itype ) { 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() = 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() = for_variable; + wcstring_list_t &for_vars = parser.current_block->state2(); 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() = 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(); 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(); + 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() != 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(); + 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() = argv[1]; parser.current_block->skip=1; - parser.current_block->param2.switch_taken=0; + parser.current_block->state2() = 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() ) { 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(); + 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() = 1; break; } } diff --git a/builtin_set.cpp b/builtin_set.cpp index 18ee5993d..670f665fc 100644 --- a/builtin_set.cpp +++ b/builtin_set.cpp @@ -822,10 +822,6 @@ static int builtin_set( parser_t &parser, wchar_t **argv ) std::vector 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 ); diff --git a/event.cpp b/event.cpp index acb9af1fd..3734ef321 100644 --- a/event.cpp +++ b/event.cpp @@ -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 *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; parser.eval( buffer.c_str(), 0, TOP ); parser.pop_block(); proc_pop_interactive(); diff --git a/event.h b/event.h index fe235da6d..766f37968 100644 --- a/event.h +++ b/event.h @@ -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 *out ); /** Fire the specified event. The function_name field of the event must diff --git a/exec.cpp b/exec.cpp index 1361955d4..adf019aa5 100644 --- a/exec.cpp +++ b/exec.cpp @@ -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() = p; + parser.current_block->state1() = p->argv0(); /* diff --git a/input.cpp b/input.cpp index e1b5f0c5d..60aa3e527 100644 --- a/input.cpp +++ b/input.cpp @@ -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; iname ); + result.push_back(wcstring(m->name)); } + return result; } wcstring_list_t input_function_get_names( void ) diff --git a/input.h b/input.h index 78131744c..5669db3fd 100644 --- a/input.h +++ b/input.h @@ -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 ); /** diff --git a/parser.cpp b/parser.cpp index ebffb6e86..82407bf0e 100644 --- a/parser.cpp +++ b/parser.cpp @@ -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() )); 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(); + 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(); + 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(); + 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(); + 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(); + 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() == WHILE_TEST_AGAIN ) { - current_block->param1.while_state = WHILE_TEST_FIRST; + current_block->state1() = 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() = 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()=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() != 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() ) { case WHILE_TEST_FIRST: { current_block->skip = proc_get_last_status()!= 0; - current_block->param1.while_state=WHILE_TESTED; + current_block->state1()=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()) && (!current_block->skip) ) { current_block->skip = proc_get_last_status()!= 0; - current_block->param1.if_state++; + current_block->state1()++; } } diff --git a/parser.h b/parser.h index e870481d3..a08500db2 100644 --- a/parser.h +++ b/parser.h @@ -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 +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; /** + T& state1(void) { + block_state_t *state; + if (state1_ptr == NULL) { + state = new block_state_t(); + state1_ptr = state; + } else { + state = dynamic_cast *>(state1_ptr); + assert(state != NULL); + } + return state->value; + } + + /** Second block type specific variable */ + block_state_base_t *state2_ptr; + + template + T& state2(void) { + block_state_t *state; + if (state2_ptr == NULL) { + state = new block_state_t(); + state2_ptr = state; + } else { + state = dynamic_cast *>(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 */ diff --git a/wildcard.cpp b/wildcard.cpp index 4ddbdc51c..406a9aa46 100644 --- a/wildcard.cpp +++ b/wildcard.cpp @@ -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 ); } diff --git a/wildcard.h b/wildcard.h index 9da7d716b..8425c5cb4 100644 --- a/wildcard.h +++ b/wildcard.h @@ -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 ); /**