diff options
-rw-r--r-- | Makefile.in | 20 | ||||
-rw-r--r-- | builtin.c | 24 | ||||
-rw-r--r-- | common.c | 52 | ||||
-rw-r--r-- | common.h | 19 | ||||
-rw-r--r-- | complete.c | 46 | ||||
-rw-r--r-- | event.c | 15 | ||||
-rw-r--r-- | exec.c | 1 | ||||
-rw-r--r-- | expand.c | 33 | ||||
-rw-r--r-- | expand.h | 5 | ||||
-rw-r--r-- | fish_pager.c | 7 | ||||
-rw-r--r-- | halloc.c | 36 | ||||
-rw-r--r-- | halloc.h | 33 | ||||
-rw-r--r-- | halloc_util.c | 69 | ||||
-rw-r--r-- | halloc_util.h | 29 | ||||
-rw-r--r-- | highlight.c | 4 | ||||
-rw-r--r-- | history.c | 6 | ||||
-rw-r--r-- | input.c | 5 | ||||
-rw-r--r-- | main.c | 15 | ||||
-rw-r--r-- | output.c | 13 | ||||
-rw-r--r-- | output.h | 10 | ||||
-rw-r--r-- | parse_util.c | 67 | ||||
-rw-r--r-- | parse_util.h | 11 | ||||
-rw-r--r-- | parser.c | 132 | ||||
-rw-r--r-- | proc.c | 1 | ||||
-rw-r--r-- | signal.c | 20 | ||||
-rw-r--r-- | translate.c | 47 | ||||
-rw-r--r-- | translate.h | 8 |
27 files changed, 379 insertions, 349 deletions
diff --git a/Makefile.in b/Makefile.in index fad72da0..c57da135 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 @@ -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<al_get_count( events ); i++ ) { event_t *e = (event_t *)al_get( events, i ); @@ -20,7 +20,6 @@ parts of fish. #include <errno.h> #include <limits.h> #include <stdarg.h> -#include <signal.h> #include <locale.h> #include <time.h> #include <sys/time.h> @@ -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; i<al_get_count( l ); i++ ) { res[i] = (wchar_t *)al_get(l,i); - if( context ) - halloc_register( context, res[i] ); } res[i]='\0'; return res; } -void block() -{ - block_count++; - if( block_count == 1 ) - { - sigset_t chldset; - sigemptyset( &chldset ); - sigaddset( &chldset, SIGCHLD ); - sigprocmask(SIG_BLOCK, &chldset, 0); - } -} - - -void unblock() -{ - block_count--; - if( block_count == 0 ) - { - sigset_t chldset; - sigemptyset( &chldset ); - sigaddset( &chldset, SIGCHLD ); - sigprocmask(SIG_UNBLOCK, &chldset, 0); - } -} - - - int fgetws2( wchar_t **b, int *len, FILE *f ) { int i=0; @@ -174,8 +141,6 @@ int fgetws2( wchar_t **b, int *len, FILE *f ) watching for EINTR errors, bytes are lost. */ - block(); - while( 1 ) { /* Reallocate the buffer if necessary */ @@ -214,8 +179,6 @@ int fgetws2( wchar_t **b, int *len, FILE *f ) case L'\n': case L'\0': buff[i]=L'\0'; - unblock(); - return i; /* Ignore carriage returns */ case L'\r': @@ -228,7 +191,6 @@ int fgetws2( wchar_t **b, int *len, FILE *f ) } - unblock(); } @@ -88,7 +88,7 @@ extern wchar_t *program_name; is not noll, all elements of the \c array_list_t are also registered to \c context using \c halloc_register(). */ -wchar_t **list_to_char_arr( void *context, array_list_t *l ); +wchar_t **list_to_char_arr( array_list_t *l ); /** Read a line from the stream f into the buffer buff of length len. If @@ -236,7 +236,12 @@ int writeb( tputs_arg_t b ); void die_mem(); /** - Clean up + Create global_context using halloc +*/ +void common_init(); + +/** + Free global_context using halloc_free */ void common_destroy(); @@ -283,16 +288,6 @@ wchar_t *unescape( const wchar_t * in, int escape_special ); /** - Block SIGCHLD. Calls to block/unblock may be nested, and only once the nest count reaches zero wiull the block be removed. -*/ -void block(); - -/** - undo call to block(). -*/ -void unblock(); - -/** Attempt to acquire a lock based on a lockfile, waiting LOCKPOLLINTERVAL milliseconds between polls and timing out after timeout seconds, thereafter forcibly attempting to obtain the lock if force is non-zero. @@ -38,7 +38,7 @@ #include "intern.h" #include "translate.h" #include "parse_util.h" - +#include "halloc_util.h" #include "wutil.h" @@ -222,10 +222,6 @@ static hash_table_t *condition_cache=0; static string_buffer_t *get_desc_buff=0; -void complete_init() -{ -} - /** This command clears the cache of condition tests created by \c condition_test(). */ @@ -322,6 +318,10 @@ static void clear_hash_entry( const void *key, const void *data ) free( (void *)data ); } +void complete_init() +{ +} + void complete_destroy() { complete_entry *i=first_entry, *prev; @@ -341,14 +341,6 @@ void complete_destroy() free( suffix_hash ); suffix_hash=0; } - - if( get_desc_buff ) - { - sb_destroy( get_desc_buff ); - free( get_desc_buff ); - get_desc_buff = 0; - } - } /** @@ -885,14 +877,13 @@ const wchar_t *complete_get_desc( const wchar_t *filename ) if( !get_desc_buff ) { - get_desc_buff = malloc(sizeof(string_buffer_t) ); - sb_init( get_desc_buff ); + get_desc_buff = sb_halloc( global_context); } else { sb_clear( get_desc_buff ); } - + if( lwstat( filename, &buf )==0) { if( S_ISCHR(buf.st_mode) ) @@ -1005,7 +996,8 @@ static void copy_strings_with_prefix( array_list_t *comp_out, int i; wchar_t *wc; - wc = expand_one( wcsdup(wc_escaped), EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_WILDCARDS); + wc = expand_one( 0, + wcsdup(wc_escaped), EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_WILDCARDS); if(!wc) return; @@ -1201,7 +1193,8 @@ static void complete_cmd( const wchar_t *cmd, array_list_t tmp; al_init( &tmp ); - if( expand_string( wcsdup(cmd), + if( expand_string( 0, + wcsdup(cmd), comp, ACCEPT_INCOMPLETE | EXECUTABLES_ONLY ) != EXPAND_ERROR ) { @@ -1227,9 +1220,10 @@ static void complete_cmd( const wchar_t *cmd, al_init( &tmp ); - if( expand_string( nxt_completion, - &tmp, - ACCEPT_INCOMPLETE | + if( expand_string( 0, + nxt_completion, + &tmp, + ACCEPT_INCOMPLETE | EXECUTABLES_ONLY ) != EXPAND_ERROR ) { for( i=0; i<al_get_count(&tmp); i++ ) @@ -1285,8 +1279,9 @@ static void complete_cmd( const wchar_t *cmd, al_init( &tmp ); - if( expand_string( nxt_completion, - &tmp, + if( expand_string( 0, + nxt_completion, + &tmp, ACCEPT_INCOMPLETE | DIRECTORIES_ONLY ) != EXPAND_ERROR ) { @@ -1672,7 +1667,10 @@ static void complete_param_expand( wchar_t *str, comp_str, do_file?L"0":L"EXPAND_SKIP_WILDCARDS" ); - expand_string( wcsdup(comp_str), comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | (do_file?0:EXPAND_SKIP_WILDCARDS) ); + expand_string( 0, + wcsdup(comp_str), + comp_out, + EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | (do_file?0:EXPAND_SKIP_WILDCARDS) ); } /** @@ -21,6 +21,7 @@ #include "event.h" #include "signal.h" #include "translate.h" +#include "halloc_util.h" /** Number of signals that can be queued before an overflow occurs @@ -194,10 +195,7 @@ const wchar_t *event_get_desc( event_t *e ) { if( !get_desc_buff ) { - get_desc_buff=malloc(sizeof(string_buffer_t) ); - if( !get_desc_buff ) - die_mem(); - sb_init( get_desc_buff ); + get_desc_buff=sb_halloc( global_context ); } else { @@ -255,7 +253,7 @@ void event_add_handler( event_t *event ) e = event_copy( event, 0 ); if( !events ) - events = al_new(); + events = al_new(); if( e->type == 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 ) @@ -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 @@ -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; i<al_get_count( end_out ); i++ ) + { + halloc_register( context, al_get( end_out, i ) ); + } + } + return res; } -wchar_t *expand_one( wchar_t *string, int flags ) +wchar_t *expand_one( void *context, wchar_t *string, int flags ) { array_list_t l; int res; wchar_t *one; if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( string ) ) + { + halloc_register( context, string ); return string; - + } + al_init( &l ); - res = expand_string( string, &l, flags ); + res = expand_string( 0, string, &l, flags ); if( !res ) { one = 0; @@ -1632,6 +1649,8 @@ wchar_t *expand_one( wchar_t *string, int flags ) al_foreach( &l, (void(*)(const void *))&free ); al_destroy( &l ); + + halloc_register( context, string ); return one; } @@ -130,7 +130,7 @@ enum \param out The list to which the result will be appended. \return One of EXPAND_OK, EXPAND_ERROR, EXPAND_WILDCARD_MATCH and EXPAND_WILDCARD_NO_MATCH */ -int expand_string( wchar_t *in, array_list_t *out, int flag ); +int expand_string( void *context, wchar_t *in, array_list_t *out, int flag ); /** expand_one is identical to expand_string, except it will fail if in @@ -141,14 +141,13 @@ int expand_string( wchar_t *in, array_list_t *out, int flag ); \param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_SUBSHELL EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS \return The expanded parameter, or 0 on failiure */ -wchar_t *expand_one( wchar_t *in, int flag ); +wchar_t *expand_one( void *context, wchar_t *in, int flag ); /** Convert the variable value to a human readable form, i.e. escape things, handle arrays, etc. Suitable for pretty-printing. */ wchar_t *expand_escape_variable( const wchar_t *in ); - /** Perform tilde expansion and nothing else on the specified string. diff --git a/fish_pager.c b/fish_pager.c index 2aefdb97..a1a30534 100644 --- a/fish_pager.c +++ b/fish_pager.c @@ -887,7 +887,7 @@ static void init() */ sb_init( &out_buff ); - output_init(); + halloc_util_init(); env_universal_init( 0, 0, 0, 0); input_common_init( &interrupt_handler ); @@ -914,6 +914,9 @@ static void init() pager_modes.c_cc[VMIN]=1; pager_modes.c_cc[VTIME]=0; + /* + + */ if( tcsetattr(0,TCSANOW,&pager_modes)) /* set the new modes */ { wperror(L"tcsetattr"); @@ -932,7 +935,7 @@ void destroy() { env_universal_destroy(); input_common_destroy(); - output_destroy(); + halloc_util_destroy(); del_curterm( cur_term ); sb_destroy( &out_buff ); fclose( out_file ); @@ -18,7 +18,6 @@ typedef struct halloc { array_list_t children; - array_list_t hchildren; long long data[0]; } halloc_t; @@ -30,49 +29,52 @@ static halloc_t *halloc_from_data( void *data ) void *halloc( void *context, size_t size ) -{ - +{ halloc_t *me, *parent; me = (halloc_t *)calloc( 1, sizeof(halloc_t) + size ); - + if( !me ) return 0; - + al_init( &me->children ); - + 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 ) +void halloc_register_function( void *context, void (*func)(void *), void *data ) { halloc_t *me; if( !context ) - return data; + return; me = halloc_from_data( context ); + al_push( &me->children, func ); al_push( &me->children, data ); - return data; } - void halloc_free( void *context ) { halloc_t *me; + int i; + 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 ); + for( i=0; i<al_get_count(&me->children); 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 ); - al_destroy( &me->hchildren ); free(me); } - @@ -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 00000000..bc575f7e --- /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 <stdlib.h> +#include <unistd.h> + +#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 00000000..c58dff20 --- /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 79cf45d3..1a7156d6 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. @@ -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() @@ -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; @@ -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; @@ -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(); @@ -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 e9eb1d03..dbcffdb2 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 923490d6..847260bd 100644 --- a/parse_util.h +++ b/parse_util.h @@ -8,6 +8,7 @@ #include <wchar.h> + /** 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 @@ -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; } @@ -109,6 +109,7 @@ void proc_init() sb_init( &event_status ); } + /** Remove job from list of jobs */ @@ -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 c26be6fc..4a109ecd 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<BUFF_COUNT; i++ ) + sb_destroy( &buff[i] ); + + free( wcs2str_buff ); +} + static void internal_init() { int i; @@ -52,7 +68,10 @@ static void internal_init() is_init = 1; for(i=0; i<BUFF_COUNT; i++ ) + { sb_init( &buff[i] ); + } + halloc_register_function_void( global_context, &internal_destroy ); bindtextdomain( PACKAGE_NAME, LOCALEDIR ); textdomain( PACKAGE_NAME ); @@ -103,26 +122,6 @@ const wchar_t *wgettext( const wchar_t *in ) return wres; } - -void translate_init() -{ -} - -void translate_destroy() -{ - int i; - - if( !is_init ) - return; - - is_init = 0; - - for(i=0; i<BUFF_COUNT; i++ ) - sb_destroy( &buff[i] ); - - free( wcs2str_buff ); -} - #else const wchar_t *wgettext( const wchar_t *in ) @@ -130,12 +129,4 @@ const wchar_t *wgettext( const wchar_t *in ) return in; } -void translate_init() -{ -} - -void translate_destroy() -{ -} - #endif diff --git a/translate.h b/translate.h index 22d3848f..19123587 100644 --- a/translate.h +++ b/translate.h @@ -19,11 +19,3 @@ Translation library, internally uses catgets */ const wchar_t *wgettext( const wchar_t *in ); -/** - Initialize (or reinitialize) the translation library -*/ -void translate_init(); -/** - Free memory used by the translation library -*/ -void translate_destroy(); |