From d1c9bca2e9f0eaac2fb8e00e5ed07e8e2906bb02 Mon Sep 17 00:00:00 2001 From: axel Date: Fri, 10 Feb 2006 01:50:20 +1000 Subject: [PATCH] Another halloc:ification of fish. Halloc has been extended to allow registering function calls, this has allowed the creation of halloc-handled arraylists, stringbuffers, etc. More job parsing halloc-ification has reduced the error handling code to only a shadow of it's former self darcs-hash:20060209155020-ac50b-e119c5293ce2368e252cfc01b98ab7c629fdd678.gz --- Makefile.in | 20 ++++---- builtin.c | 24 +++++---- common.c | 52 +++----------------- common.h | 19 +++----- complete.c | 46 +++++++++--------- event.c | 15 ++---- exec.c | 1 + expand.c | 33 ++++++++++--- expand.h | 5 +- fish_pager.c | 7 ++- halloc.c | 56 ++++++++++----------- halloc.h | 33 +++++++------ halloc_util.c | 69 ++++++++++++++++++++++++++ halloc_util.h | 29 +++++++++++ highlight.c | 4 +- history.c | 6 +-- input.c | 5 +- main.c | 15 +++--- output.c | 13 +++-- output.h | 10 ---- parse_util.c | 67 ++++++++++++------------- parse_util.h | 11 +---- parser.c | 132 ++++++++++++++++++++++---------------------------- proc.c | 1 + signal.c | 20 ++++++-- translate.c | 47 ++++++++---------- translate.h | 8 --- 27 files changed, 389 insertions(+), 359 deletions(-) create mode 100644 halloc_util.c create mode 100644 halloc_util.h diff --git a/Makefile.in b/Makefile.in index fad72da0f..c57da1352 100644 --- a/Makefile.in +++ b/Makefile.in @@ -59,14 +59,16 @@ INIT_DIR_INSTALL = init/fish_interactive.fish init/fish_function.fish init/fish_ # Set to 1 if we have gettext HAVE_GETTEXT=@HAVE_GETTEXT@ +CORE_OBJS := util.o common.o halloc.o halloc_util.o + # All objects used by fish, that are compiled from an ordinary .c file # using an ordinary .h file. -COMMON_OBJS := function.o builtin.o common.o complete.o env.o exec.o \ +COMMON_OBJS := function.o builtin.o complete.o env.o exec.o \ expand.o highlight.o history.o kill.o parser.o proc.o reader.o \ - sanity.o tokenizer.o util.o wildcard.o wgetopt.o wutil.o input.o \ + sanity.o tokenizer.o wildcard.o wgetopt.o wutil.o input.o \ output.o intern.o env_universal.o env_universal_common.o \ input_common.o event.o signal.o io.o translate.o parse_util.o \ - halloc.o + $(CORE_OBJS) # builtin_help.h exists, but builtin_help.c is autogenerated COMMON_OBJS_WITH_HEADER := builtin_help.o @@ -80,21 +82,21 @@ FISH_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) \ $(COMMON_OBJS_WITH_HEADER) main.o # All objects that the system needs to build fish_pager -FISH_PAGER_OBJS := fish_pager.o common.o output.o util.o wutil.o \ +FISH_PAGER_OBJS := fish_pager.o output.o wutil.o \ tokenizer.o input_common.o env_universal.o env_universal_common.o \ - translate.o halloc.o + translate.o $(CORE_OBJS) # All objects that the system needs to build fish_tests FISH_TESTS_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) \ $(COMMON_OBJS_WITH_HEADER) fish_tests.o # All objects that the system needs to build fishd -FISHD_OBJS := fishd.o env_universal_common.o common.o util.o wutil.o \ - doc_src/fishd.o halloc.o +FISHD_OBJS := fishd.o env_universal_common.o wutil.o \ + doc_src/fishd.o $(CORE_OBJS) # All objects needed to build mimedb -MIME_OBJS := mimedb.o xdgmimealias.o xdgmime.o xdgmimeglob.o \ - xdgmimeint.o xdgmimemagic.o xdgmimeparent.o wutil.o halloc.o +MIME_OBJS := mimedb.o xdgmimealias.o xdgmime.o xdgmimeglob.o \ + xdgmimeint.o xdgmimemagic.o xdgmimeparent.o wutil.o # # Files containing documentation for builtins. Should be listed diff --git a/builtin.c b/builtin.c index b049d3c14..cb3d9fac9 100644 --- a/builtin.c +++ b/builtin.c @@ -60,6 +60,7 @@ #include "signal.h" #include "translate.h" #include "halloc.h" +#include "halloc_util.h" /** The default prompt for the read command @@ -496,7 +497,7 @@ static int builtin_builtin( wchar_t **argv ) al_init( &names ); builtin_get_names( &names ); - names_arr = list_to_char_arr( 0, &names ); + names_arr = list_to_char_arr( &names ); qsort( names_arr, al_get_count( &names ), sizeof(wchar_t *), @@ -511,7 +512,7 @@ static int builtin_builtin( wchar_t **argv ) L"\n", (void *)0 ); } - halloc_free( names_arr ); + free( names_arr ); al_destroy( &names ); } return 0; @@ -813,7 +814,7 @@ static int builtin_functions( wchar_t **argv ) al_init( &names ); function_get_names( &names, show_hidden ); - names_arr = list_to_char_arr( 0, &names ); + names_arr = list_to_char_arr( &names ); qsort( names_arr, al_get_count( &names ), sizeof(wchar_t *), @@ -845,7 +846,7 @@ static int builtin_functions( wchar_t **argv ) } } - halloc_free( names_arr ); + free( names_arr ); al_destroy( &names ); return 0; } @@ -858,7 +859,7 @@ static int builtin_functions( wchar_t **argv ) sb_append( sb_out, _( L"Current function definitions are:\n\n" ) ); al_init( &names ); function_get_names( &names, show_hidden ); - names_arr = list_to_char_arr( 0, &names ); + names_arr = list_to_char_arr( &names ); qsort( names_arr, al_get_count( &names ), sizeof(wchar_t *), @@ -867,7 +868,7 @@ static int builtin_functions( wchar_t **argv ) { functions_def( names_arr[i] ); } - halloc_free( names_arr ); + free( names_arr ); al_destroy( &names ); break; } @@ -924,8 +925,7 @@ static int builtin_function( wchar_t **argv ) woptind=0; parser_push_block( FUNCTION_DEF ); - events=halloc( current_block, sizeof(array_list_t ) ); - al_init( events ); + events=al_halloc( current_block ); const static struct woption long_options[] = @@ -1160,8 +1160,6 @@ static int builtin_function( wchar_t **argv ) } } - halloc_register( current_block, events->arr ); - if( res ) { int i; @@ -1176,7 +1174,7 @@ static int builtin_function( wchar_t **argv ) al_init( &names ); function_get_names( &names, 0 ); - names_arr = list_to_char_arr( 0, &names ); + names_arr = list_to_char_arr( &names ); qsort( names_arr, al_get_count( &names ), sizeof(wchar_t *), @@ -1194,7 +1192,7 @@ static int builtin_function( wchar_t **argv ) sb_append2( sb_err, nxt, L" ", (void *)0 ); } - halloc_free( names_arr ); + free( names_arr ); al_destroy( &names ); sb_append( sb_err, L"\n" ); @@ -1207,7 +1205,7 @@ static int builtin_function( wchar_t **argv ) current_block->param2.function_description=desc?halloc_register( current_block, wcsdup(desc)):0; current_block->param3.function_is_binding = is_binding; current_block->param4.function_events = events; - + for( i=0; i #include #include -#include #include #include #include @@ -58,7 +57,6 @@ parts of fish. #include "proc.h" #include "wildcard.h" #include "parser.h" -#include "halloc.h" /** The maximum number of minor errors to report. Further errors will be omitted. @@ -95,20 +93,14 @@ int debug_level=1; */ static struct winsize termsize; - -/** - Number of nested calls to the block function. Unblock when this reaches 0. -*/ -static int block_count=0; - /** String buffer used by the wsetlocale function */ static string_buffer_t *setlocale_buff=0; - void common_destroy() { + if( setlocale_buff ) { sb_destroy( setlocale_buff ); @@ -116,9 +108,13 @@ void common_destroy() } } -wchar_t **list_to_char_arr( void *context, array_list_t *l ) +void common_init() { - wchar_t ** res = halloc( context, sizeof(wchar_t *)*(al_get_count( l )+1) ); +} + +wchar_t **list_to_char_arr( array_list_t *l ) +{ + wchar_t ** res = malloc( sizeof(wchar_t *)*(al_get_count( l )+1) ); int i; if( res == 0 ) { @@ -127,40 +123,11 @@ wchar_t **list_to_char_arr( void *context, array_list_t *l ) for( i=0; itype == EVENT_SIGNAL ) { @@ -644,13 +642,6 @@ void event_destroy() free( killme ); killme=0; } - - if( get_desc_buff ) - { - sb_destroy( get_desc_buff ); - free( get_desc_buff ); - } - } void event_free( event_t *e ) diff --git a/exec.c b/exec.c index 8e8ef1a8c..e004d17f4 100644 --- a/exec.c +++ b/exec.c @@ -38,6 +38,7 @@ #include "env_universal.h" #include "translate.h" #include "halloc.h" +#include "halloc_util.h" /** Prototype for the getpgid library function. The prototype for this diff --git a/expand.c b/expand.c index 65450959f..534997a75 100644 --- a/expand.c +++ b/expand.c @@ -36,6 +36,7 @@ parameter expansion. #include "expand.h" #include "wildcard.h" #include "exec.h" +#include "signal.h" #include "tokenizer.h" #include "complete.h" #include "translate.h" @@ -557,8 +558,10 @@ static int find_process( const wchar_t *proc, continue; } + signal_block(); fgetws2( &cmd, &sz, cmdfile ); - + signal_unblock(); + fclose( cmdfile ); } else @@ -903,9 +906,9 @@ static int expand_variables( wchar_t *in, array_list_t *out ) { string_buffer_t res; sb_init( &res ); - + in[i]=0; - + sb_append( &res, in ); sb_append_char( &res, INTERNAL_SEPARATOR ); @@ -1393,7 +1396,8 @@ static void remove_internal_separator( const void *s, int conv ) /** The real expansion function. expand_one is just a wrapper around this one. */ -int expand_string( wchar_t *str, +int expand_string( void *context, + wchar_t *str, array_list_t *end_out, int flags ) { @@ -1403,12 +1407,14 @@ int expand_string( wchar_t *str, int i; int subshell_ok = 1; int res = EXPAND_OK; + int start_count = al_get_count( end_out ); // debug( 1, L"Expand %ls", str ); if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( str ) ) { + halloc_register( context, str ); al_push( end_out, str ); return EXPAND_OK; } @@ -1597,22 +1603,33 @@ int expand_string( wchar_t *str, al_destroy( out ); } + if( context ) + { + for( i=start_count; ichildren ); - + if( context ) { parent = halloc_from_data( context ); - al_push( &parent->hchildren, &me->data ); + al_push( &parent->children, &halloc_free ); + al_push( &parent->children, &me->data ); } - + return &me->data; } -void *halloc_register( void *context, void *data ) -{ - halloc_t *me; - if( !context ) - return data; - - me = halloc_from_data( context ); - al_push( &me->children, data ); - return data; -} - - -void halloc_free( void *context ) +void halloc_register_function( void *context, void (*func)(void *), void *data ) { halloc_t *me; if( !context ) return; - + me = halloc_from_data( context ); - al_foreach( &me->hchildren, (void (*)(const void *))&halloc_free ); - al_foreach( &me->children, (void (*)(const void *))&free ); - al_destroy( &me->children ); - al_destroy( &me->hchildren ); - free(me); + al_push( &me->children, func ); + al_push( &me->children, data ); } +void halloc_free( void *context ) +{ + halloc_t *me; + int i; + + if( !context ) + return; + + me = halloc_from_data( context ); + for( i=0; ichildren); i+=2 ) + { + void (*func)(void *) = (void (*)(void *))al_get( &me->children, i ); + void * data = (void *)al_get( &me->children, i+1 ); + func( data ); + } + al_destroy( &me->children ); + free(me); +} diff --git a/halloc.h b/halloc.h index 089318901..6dfdb4e22 100644 --- a/halloc.h +++ b/halloc.h @@ -6,30 +6,33 @@ */ +#ifndef FISH_HALLOC_H +#define FISH_HALLOC_H + /** - Allocate new memory using specified parent memory context. If \c - context is null, a new root context is created. Context _must_ be - either 0 or the result of a previous call to halloc. + Allocate new memory using specified parent memory context. Context + _must_ be either 0 or the result of a previous call to halloc. - If \c context is null, the resulting block must be freed with a - call to halloc_free(). + If \c context is null, the resulting block is a root context, and + must be freed with a call to halloc_free(). - If \c context is not null, the resulting memory block must never be - explicitly freed, it will be automatically freed whenever the - parent context is freed. + If \c context is not null, the resulting memory block is a child + context, and must never be explicitly freed, it will be + automatically freed whenever the parent context is freed. */ void *halloc( void *context, size_t size ); +/** + Make the specified function run whenever context is free'd, using data as argument. +*/ +void halloc_register_function( void *context, void (*func)(void *), void *data ); + /** Free memory context and all children contexts. Only root contexts may be freed explicitly. */ void halloc_free( void *context ); -/** - Free the memory pointed to by \c data when the memory pointed to by - \c context is free:d. Note that this will _not_ turn the specified - memory area into a valid halloc context. Only memory areas created - using a call to halloc() can be used as a context. -*/ -void *halloc_register( void *context, void *data ); + +#endif + diff --git a/halloc_util.c b/halloc_util.c new file mode 100644 index 000000000..bc575f7ee --- /dev/null +++ b/halloc_util.c @@ -0,0 +1,69 @@ +/** \file halloc.c + + A hierarchical memory allocation system. Works just like talloc + used in Samba, except that an arbitrary block allocated with + malloc() can be registered to be freed by halloc_free. + +*/ + +#include "config.h" + +#include +#include + +#include "util.h" +#include "common.h" +#include "halloc.h" + +void *global_context=0; + +void halloc_util_init() +{ + global_context = halloc( 0, 0 ); +} + +void halloc_util_destroy() +{ + halloc_free( global_context ); +} + +array_list_t *al_halloc( void *context ) +{ + array_list_t *res = halloc( context, sizeof( array_list_t ) ); + if( !res ) + die_mem(); + al_init( res ); + halloc_register_function( res, (void (*)(void *)) &al_destroy, res ); + return res; +} + +string_buffer_t *sb_halloc( void *context ) +{ + string_buffer_t *res = halloc( context, sizeof( string_buffer_t ) ); + if( !res ) + die_mem(); + sb_init( res ); + halloc_register_function( res, (void (*)(void *)) &sb_destroy, res ); + return res; +} + +static void halloc_passthrough( void *f ) +{ + void (*func)() = (void (*)() )f; + func(); +} + +void halloc_register_function_void( void *context, void (*func)() ) +{ + halloc_register_function( context, &halloc_passthrough, (void *)func ); +} + +void *halloc_register( void *context, void *data ) +{ + if( !data ) + return 0; + + halloc_register_function( context, &free, data ); + return data; +} + diff --git a/halloc_util.h b/halloc_util.h new file mode 100644 index 000000000..c58dff206 --- /dev/null +++ b/halloc_util.h @@ -0,0 +1,29 @@ +/** + \file halloc_util.h + + Various halloc-related utility functions. +*/ + +#ifndef FISH_HALLOC_UTIL_H +#define FISH_HALLOC_UTIL_H + +extern void *global_context; + +void halloc_util_init(); + +void halloc_util_destroy(); + + +array_list_t *al_halloc( void *context ); + +string_buffer_t *sb_halloc( void *context ); + +void halloc_register_function_void( void *context, void (*func)() ); +/** + Free the memory pointed to by \c data when the memory pointed to by + \c context is free:d. Note that this will _not_ turn the specified + memory area into a valid halloc context. Only memory areas created + using a call to halloc() can be used as a context. +*/ +void *halloc_register( void *context, void *data ); +#endif diff --git a/highlight.c b/highlight.c index 79cf45d37..1a7156d6f 100644 --- a/highlight.c +++ b/highlight.c @@ -132,7 +132,7 @@ void highlight_shell( wchar_t * buff, */ wchar_t *cmd = (last_type == TOK_STRING) ? - expand_one(wcsdup(tok_last( &tok )),EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES) : + expand_one( 0, wcsdup(tok_last( &tok )),EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES) : wcsdup(tok_last( &tok )); if( cmd == 0 ) { @@ -248,7 +248,7 @@ void highlight_shell( wchar_t * buff, { case TOK_STRING: { - target = expand_one( wcsdup( tok_last( &tok ) ), EXPAND_SKIP_SUBSHELL); + target = expand_one( 0, wcsdup( tok_last( &tok ) ), EXPAND_SKIP_SUBSHELL); /* Redirect filename may contain a subshell. If so, it will be ignored/not flagged. diff --git a/history.c b/history.c index 887fb0856..aa8d9f78e 100644 --- a/history.c +++ b/history.c @@ -102,7 +102,7 @@ static void history_load() is_loaded = 1; - block(); + signal_block(); hash_init2( &used, &hash_wcs_func, &hash_wcs_cmp, @@ -124,7 +124,7 @@ static void history_load() fclose( in_stream ); free( fn ); free( buff ); - unblock(); + signal_unblock(); return; } @@ -181,7 +181,7 @@ static void history_load() free( buff ); free( fn ); last_loaded = history_last; - unblock(); + signal_unblock(); } void history_init() diff --git a/input.c b/input.c index f7ad7e22c..bbb4a8c42 100644 --- a/input.c +++ b/input.c @@ -55,6 +55,7 @@ implementation in fish is as of yet incomplete. #include "env.h" #include "expand.h" #include "event.h" +#include "signal.h" #include "translate.h" static void input_read_inputrc( wchar_t *fn ); @@ -1085,7 +1086,7 @@ static void input_read_inputrc( wchar_t *fn ) int error=0; // fwprintf( stderr, L"read %ls\n", fn ); - block(); + signal_block(); rc = wfopen( fn, "r" ); if( rc ) @@ -1120,7 +1121,7 @@ static void input_read_inputrc( wchar_t *fn ) free( buff ); fclose( rc ); } - unblock(); + signal_unblock(); inputrc_skip_block_count=0; inputrc_block_count=0; diff --git a/main.c b/main.c index 1744451a3..448f61905 100644 --- a/main.c +++ b/main.c @@ -57,6 +57,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "event.h" #include "output.h" #include "translate.h" +#include "halloc_util.h" /** Parse init files @@ -73,7 +74,7 @@ static int read_init() } env_set( L"__fish_help_dir", DOCDIR, 0); - + eval( L"builtin cd " SYSCONFDIR L" 2>/dev/null; . fish 2>/dev/null", 0, TOP ); eval( L"builtin cd 2>/dev/null;. .fish 2>/dev/null", 0, TOP ); @@ -210,9 +211,10 @@ int main( int argc, char **argv ) is_interactive_session &= isatty(STDIN_FILENO); is_interactive_session |= force_interactive; - translate_init(); + common_init(); + halloc_util_init(); + proc_init(); - output_init(); event_init(); exec_init(); wutil_init(); @@ -220,7 +222,6 @@ int main( int argc, char **argv ) builtin_init(); function_init(); env_init(); - parse_util_init(); complete_init(); reader_init(); @@ -302,13 +303,11 @@ int main( int argc, char **argv ) reader_destroy(); parser_destroy(); wutil_destroy(); - common_destroy(); exec_destroy(); - parse_util_destroy(); event_destroy(); - output_destroy(); - translate_destroy(); + common_destroy(); + halloc_util_destroy(); intern_free_all(); return res; diff --git a/output.c b/output.c index a148e9263..42669d65f 100644 --- a/output.c +++ b/output.c @@ -43,6 +43,7 @@ #include "expand.h" #include "common.h" #include "output.h" +#include "halloc_util.h" #include "highlight.h" /** @@ -101,11 +102,7 @@ static size_t writestr_buff_sz=0; */ static char *writestr_buff = 0; -void output_init() -{ -} - -void output_destroy() +static void output_destroy() { free( writestr_buff ); } @@ -292,6 +289,12 @@ void writestr( const wchar_t *str ) */ if( writestr_buff_sz < len ) { + if( !writestr_buff ) + halloc_register_function_void( global_context, &output_destroy ); + + + + writestr_buff = realloc( writestr_buff, len ); if( !writestr_buff ) die_mem(); diff --git a/output.h b/output.h index 6532a48bf..ec008adc8 100644 --- a/output.h +++ b/output.h @@ -116,14 +116,4 @@ int writespace( int c ); */ int output_color_code( const wchar_t *val ); -/** - Initialize static data -*/ -void output_init(); - -/** - Destroy static data -*/ -void output_destroy(); - #endif diff --git a/parse_util.c b/parse_util.c index e9eb1d039..dbcffdb22 100644 --- a/parse_util.c +++ b/parse_util.c @@ -24,6 +24,7 @@ #include "expand.h" #include "intern.h" #include "exec.h" +#include "halloc_util.h" /** Set of files which have been autoloaded @@ -427,6 +428,36 @@ void parse_util_token_extent( const wchar_t *buff, } +/** + Free hash value, but not hash key +*/ +static void clear_hash_value( const void *key, const void *data ) +{ + free( (void *)data ); +} + +static void clear_loaded_entry( const void *key, const void *data ) +{ + hash_table_t *loaded = (hash_table_t *)data; + hash_foreach( loaded, + &clear_hash_value ); + hash_destroy( loaded ); + free( loaded ); + free( (void *)key ); +} + +static void parse_util_destroy() +{ + if( all_loaded ) + { + hash_foreach( all_loaded, + &clear_loaded_entry ); + + hash_destroy( all_loaded ); + free( all_loaded ); + all_loaded = 0; + } +} int parse_util_load( const wchar_t *cmd, const wchar_t *path_var, @@ -469,6 +500,7 @@ int parse_util_load( const wchar_t *cmd, } hash_init( loaded, &hash_wcs_func, &hash_wcs_cmp ); hash_put( all_loaded, wcsdup(path_var), loaded ); + halloc_register_function_void( global_context, &parse_util_destroy ); } /* @@ -564,38 +596,3 @@ int parse_util_load( const wchar_t *cmd, return reloaded; } -void parse_util_init() -{ -} - -/** - Free hash value, but not hash key -*/ -static void clear_hash_value( const void *key, const void *data ) -{ - free( (void *)data ); -} - -static void clear_loaded_entry( const void *key, const void *data ) -{ - hash_table_t *loaded = (hash_table_t *)data; - hash_foreach( loaded, - &clear_hash_value ); - hash_destroy( loaded ); - free( loaded ); - free( (void *)key ); -} - -void parse_util_destroy() -{ - if( all_loaded ) - { - hash_foreach( all_loaded, - &clear_loaded_entry ); - - hash_destroy( all_loaded ); - free( all_loaded ); - all_loaded = 0; - } -} - diff --git a/parse_util.h b/parse_util.h index 923490d62..847260bd4 100644 --- a/parse_util.h +++ b/parse_util.h @@ -8,6 +8,7 @@ #include + /** Locate the first subshell in the specified string. @@ -78,14 +79,4 @@ int parse_util_load( const wchar_t *cmd, void (*on_load)(const wchar_t *cmd), int reload ); -/** - Init the parser utility library -*/ -void parse_util_init(); - -/** - Free resources used by the parser utility library -*/ -void parse_util_destroy(); - #endif diff --git a/parser.c b/parser.c index 666ca769a..3db7b4b00 100644 --- a/parser.c +++ b/parser.c @@ -39,6 +39,7 @@ The fish parser. Contains functions for parsing code. #include "intern.h" #include "parse_util.h" #include "halloc.h" +#include "halloc_util.h" /** Maximum number of block levels in code. This is not the same as @@ -340,15 +341,15 @@ static int block_count( block_t *b ) void parser_push_block( int type ) { block_t *new = halloc( 0, sizeof( block_t )); - + new->src_lineno = parser_get_lineno(); new->src_filename = parser_current_filename()?intern(parser_current_filename()):0; // debug( 3, L"Block push %ls %d\n", parser_get_block_desc(type), block_count( current_block)+1 ); - + new->outer = current_block; new->type = (current_block && current_block->skip)?FAKE:type; - + /* New blocks should be skipped if the outer block is skipped, except TOP ans SUBST block, which open up new environments. Fake @@ -359,9 +360,8 @@ void parser_push_block( int type ) new->skip = 0; if( type == FAKE ) new->skip = 1; - + new->job = 0; - new->loop_status=LOOP_NORMAL; current_block = new; @@ -371,20 +371,12 @@ void parser_push_block( int type ) (new->type != TOP) ) { env_push( type == FUNCTION_CALL ); + halloc_register_function_void( current_block, &env_pop ); } } void parser_pop_block() { -// debug( 3, L"Block pop %ls %d\n", parser_get_block_desc(current_block->type), block_count(current_block)-1 ); - - if( (current_block->type != FUNCTION_DEF ) && - (current_block->type != FAKE) && - (current_block->type != TOP) ) - { - env_pop(); - } - block_t *old = current_block; current_block = current_block->outer; halloc_free( old ); @@ -744,11 +736,10 @@ wchar_t *get_filename( const wchar_t *cmd ) wchar_t *path_cpy = wcsdup( path ); wchar_t *nxt_path = path; wchar_t *state; - + if( (new_cmd==0) || (path_cpy==0) ) { die_mem(); - } for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state ); @@ -940,7 +931,7 @@ int eval_args( const wchar_t *line, array_list_t *args ) switch(tok_last_type( &tok ) ) { case TOK_STRING: - switch( expand_string( wcsdup(tok_last( &tok )), args, 0 ) ) + switch( expand_string( 0, wcsdup(tok_last( &tok )), args, 0 ) ) { case EXPAND_ERROR: { @@ -979,13 +970,12 @@ int eval_args( const wchar_t *line, array_list_t *args ) do_loop=0; break; - } } - + print_errors(); tok_destroy( &tok ); - + current_tokenizer=previous_tokenizer; current_tokenizer_pos = previous_pos; is_interactive = was_interactive; @@ -1331,7 +1321,8 @@ static void parse_job_main_loop( process_t *p, return; } p->pipe_fd = wcstol( tok_last( tok ), 0, 10 ); - p->argv = list_to_char_arr( j, args ); + p->argv = list_to_char_arr( args ); + halloc_register( j, p->argv ); p->next = halloc( j, sizeof( process_t ) ); if( p->next == 0 ) { @@ -1353,7 +1344,8 @@ static void parse_job_main_loop( process_t *p, case TOK_END: { - p->argv = list_to_char_arr( j, args ); + p->argv = list_to_char_arr( args ); + halloc_register( j, p->argv ); if( tok_has_next(tok)) tok_next(tok); @@ -1399,7 +1391,7 @@ static void parse_job_main_loop( process_t *p, } - switch( expand_string( wcsdup(tok_last( tok )), args, 0 ) ) + switch( expand_string( j, wcsdup(tok_last( tok )), args, 0 ) ) { case EXPAND_ERROR: { @@ -1487,7 +1479,7 @@ static void parse_job_main_loop( process_t *p, { case TOK_STRING: { - target = (wchar_t *)halloc_register( j, expand_one( wcsdup( tok_last( tok ) ), 0)); + target = (wchar_t *)expand_one( j, wcsdup( tok_last( tok ) ), 0); if( target == 0 && error_code == 0 ) { @@ -1634,7 +1626,7 @@ static int parse_job( process_t *p, job_t *j, tokenizer *tok ) { - array_list_t args; // The list that will become the argc array for the program + array_list_t *args = al_halloc( j ); // The list that will become the argc array for the program int use_function = 1; // May functions be considered when checking what action this command represents int use_builtin = 1; // May builtins be considered when checking what action this command represents int is_new_block=0; // Does this command create a new block? @@ -1642,28 +1634,26 @@ static int parse_job( process_t *p, block_t *prev_block = current_block; int prev_tokenizer_pos = current_tokenizer_pos; - al_init( &args ); - current_tokenizer_pos = tok_get_pos( tok ); - while( al_get_count( &args ) == 0 ) + while( al_get_count( args ) == 0 ) { wchar_t *nxt=0; switch( tok_last_type( tok )) { case TOK_STRING: { - nxt = expand_one( wcsdup(tok_last( tok )), + nxt = expand_one( j, + wcsdup(tok_last( tok )), EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES); - + if( nxt == 0 ) { error( SYNTAX_ERROR, tok_get_pos( tok ), ILLEGAL_CMD_ERR_MSG, tok_last( tok ) ); - - al_destroy( &args ); + current_tokenizer_pos = prev_tokenizer_pos; return 0; } @@ -1677,7 +1667,6 @@ static int parse_job( process_t *p, TOK_ERR_MSG, tok_last(tok) ); - al_destroy( &args ); current_tokenizer_pos = prev_tokenizer_pos; return 0; } @@ -1700,7 +1689,6 @@ static int parse_job( process_t *p, tok_get_desc( tok_last_type(tok) ) ); } - al_destroy( &args ); current_tokenizer_pos = prev_tokenizer_pos; return 0; } @@ -1712,14 +1700,16 @@ static int parse_job( process_t *p, CMD_ERR_MSG, tok_get_desc( tok_last_type(tok) ) ); - al_destroy( &args ); current_tokenizer_pos = prev_tokenizer_pos; return 0; } } - + int mark = tok_get_pos( tok ); + int consumed = 0; + + if( wcscmp( L"command", nxt )==0 ) { tok_next( tok ); @@ -1731,8 +1721,7 @@ static int parse_job( process_t *p, { use_function = 0; use_builtin=0; - free( nxt ); - continue; + consumed=1; } } else if( wcscmp( L"builtin", nxt )==0 ) @@ -1745,8 +1734,7 @@ static int parse_job( process_t *p, else { use_function = 0; - free( nxt ); - continue; + consumed=1; } } else if( wcscmp( L"not", nxt )==0 ) @@ -1759,8 +1747,7 @@ static int parse_job( process_t *p, else { j->negate=1-j->negate; - free( nxt ); - continue; + consumed=1; } } else if( wcscmp( L"and", nxt )==0 ) @@ -1773,8 +1760,7 @@ static int parse_job( process_t *p, else { j->skip = proc_get_last_status(); - free( nxt ); - continue; + consumed=1; } } else if( wcscmp( L"or", nxt )==0 ) @@ -1787,8 +1773,7 @@ static int parse_job( process_t *p, else { j->skip = !proc_get_last_status(); - free( nxt ); - continue; + consumed=1; } } else if( wcscmp( L"exec", nxt )==0 ) @@ -1798,7 +1783,6 @@ static int parse_job( process_t *p, error( SYNTAX_ERROR, tok_get_pos( tok ), EXEC_ERR_MSG ); - al_destroy( &args ); free(nxt); current_tokenizer_pos = prev_tokenizer_pos; return 0; @@ -1814,9 +1798,8 @@ static int parse_job( process_t *p, use_function = 0; use_builtin=0; p->type=INTERNAL_EXEC; - free( nxt ); + consumed=1; current_tokenizer_pos = prev_tokenizer_pos; - continue; } } else if( wcscmp( L"while", nxt ) ==0 ) @@ -1844,10 +1827,8 @@ static int parse_job( process_t *p, current_block->tok_pos = mark; } - free( nxt ); + consumed=1; is_new_block=1; - - continue; } else if( wcscmp( L"if", nxt ) ==0 ) { @@ -1858,8 +1839,12 @@ static int parse_job( process_t *p, current_block->param1.if_state=0; current_block->tok_pos = mark; - free( nxt ); is_new_block=1; + consumed=1; + } + + if( consumed ) + { continue; } @@ -1892,7 +1877,7 @@ static int parse_job( process_t *p, } } } - al_push( &args, nxt ); + al_push( args, nxt ); } if( error_code == 0 ) @@ -1900,10 +1885,10 @@ static int parse_job( process_t *p, if( !p->type ) { if( use_builtin && - builtin_exists( (wchar_t *)al_get( &args, 0 ) ) ) + builtin_exists( (wchar_t *)al_get( args, 0 ) ) ) { p->type = INTERNAL_BUILTIN; - is_new_block = parser_is_block( (wchar_t *)al_get( &args, 0 ) ); + is_new_block = parser_is_block( (wchar_t *)al_get( args, 0 ) ); } } @@ -1919,7 +1904,7 @@ static int parse_job( process_t *p, } else { - p->actual_cmd = halloc_register(j, get_filename( (wchar_t *)al_get( &args, 0 ) )); + p->actual_cmd = halloc_register(j, get_filename( (wchar_t *)al_get( args, 0 ) )); /* Check if the specified command exists @@ -1933,16 +1918,16 @@ static int parse_job( process_t *p, implicit command. */ wchar_t *pp = - parser_cdpath_get( (wchar_t *)al_get( &args, 0 ) ); + parser_cdpath_get( (wchar_t *)al_get( args, 0 ) ); if( pp ) { wchar_t *tmp; free( pp ); - tmp = (wchar_t *)al_get( &args, 0 ); - al_truncate( &args, 0 ); - al_push( &args, wcsdup( L"cd" ) ); - al_push( &args, tmp ); + tmp = (wchar_t *)al_get( args, 0 ); + al_truncate( args, 0 ); + al_push( args, wcsdup( L"cd" ) ); + al_push( args, tmp ); /* If we have defined a wrapper around cd, use it, otherwise use the cd builtin @@ -1954,12 +1939,12 @@ static int parse_job( process_t *p, } else { - if( wcschr( (wchar_t *)al_get( &args, 0 ), L'=' ) ) + if( wcschr( (wchar_t *)al_get( args, 0 ), L'=' ) ) { error( EVAL_ERROR, tok_get_pos( tok ), COMMAND_ASSIGN_ERR_MSG, - (wchar_t *)al_get( &args, 0 ) ); + (wchar_t *)al_get( args, 0 ) ); } @@ -1968,7 +1953,7 @@ static int parse_job( process_t *p, error( EVAL_ERROR, tok_get_pos( tok ), _(L"Unknown command '%ls'"), - (wchar_t *)al_get( &args, 0 ) ); + (wchar_t *)al_get( args, 0 ) ); } } @@ -1990,6 +1975,7 @@ static int parse_job( process_t *p, error( SYNTAX_ERROR, tok_get_pos( tok ), BLOCK_END_ERR_MSG ); + } if( !make_sub_block ) @@ -2028,8 +2014,8 @@ static int parse_job( process_t *p, end_pos - current_tokenizer_pos); p->type = INTERNAL_BLOCK; - free( (void *)al_get( &args, 0 ) ); - al_set( &args, 0, sub_block ); + free( (void *)al_get( args, 0 ) ); + al_set( args, 0, sub_block ); tok_set_pos( tok, end_pos ); @@ -2047,22 +2033,20 @@ static int parse_job( process_t *p, if( !error_code ) { - if( p->type == INTERNAL_BUILTIN && parser_skip_arguments( (wchar_t *)al_get(&args, 0) ) ) + if( p->type == INTERNAL_BUILTIN && parser_skip_arguments( (wchar_t *)al_get(args, 0) ) ) { - p->argv = list_to_char_arr( j, &args ); + p->argv = list_to_char_arr( args ); + halloc_register( j, p->argv ); // tok_next(tok); } else { - parse_job_main_loop( p, j, tok, &args ); + parse_job_main_loop( p, j, tok, args ); } } if( error_code ) { - if( !p->argv ) - al_foreach( &args, - (void (*)(const void *))&free ); /* Make sure the block stack is consistent */ @@ -2070,9 +2054,7 @@ static int parse_job( process_t *p, { parser_pop_block(); } - } - al_destroy( &args ); current_tokenizer_pos = prev_tokenizer_pos; return !error_code; } diff --git a/proc.c b/proc.c index 08a74cb94..f804e8bf8 100644 --- a/proc.c +++ b/proc.c @@ -109,6 +109,7 @@ void proc_init() sb_init( &event_status ); } + /** Remove job from list of jobs */ diff --git a/signal.c b/signal.c index d6f3be8cb..dbd3b701a 100644 --- a/signal.c +++ b/signal.c @@ -43,6 +43,9 @@ struct lookup_entry const wchar_t *desc; }; +static int block_count=0; + + /** Lookup table used to convert between signal names and signal ids, etc. @@ -536,13 +539,22 @@ void signal_handle( int sig, int do_handle ) void signal_block() { sigset_t chldset; - sigfillset( &chldset ); - sigprocmask(SIG_BLOCK, &chldset, 0); + + if( !block_count ) + { + sigfillset( &chldset ); + sigprocmask(SIG_BLOCK, &chldset, 0); + } + block_count++; } void signal_unblock() { sigset_t chldset; - sigfillset( &chldset ); - sigprocmask(SIG_UNBLOCK, &chldset, 0); + block_count--; + if( !block_count ) + { + sigfillset( &chldset ); + sigprocmask(SIG_UNBLOCK, &chldset, 0); + } } diff --git a/translate.c b/translate.c index c26be6fc2..4a109ecdd 100644 --- a/translate.c +++ b/translate.c @@ -17,6 +17,7 @@ Translation library, internally uses catgets #include "common.h" #include "util.h" +#include "halloc_util.h" #if HAVE_GETTEXT @@ -45,6 +46,21 @@ static size_t wcs2str_buff_count=0; static int is_init = 0; +static void internal_destroy() +{ + int i; + + if( !is_init ) + return; + + is_init = 0; + + for(i=0; i