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
This commit is contained in:
axel 2006-02-10 01:50:20 +10:00
parent 49973b85da
commit d1c9bca2e9
27 changed files with 389 additions and 359 deletions

View file

@ -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
xdgmimeint.o xdgmimemagic.o xdgmimeparent.o wutil.o
#
# Files containing documentation for builtins. Should be listed

View file

@ -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" );

View file

@ -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();
}

View file

@ -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();
@ -282,16 +287,6 @@ wchar_t *escape( const wchar_t *in,
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,

View file

@ -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,8 +877,7 @@ 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
{
@ -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,7 +1220,8 @@ static void complete_cmd( const wchar_t *cmd,
al_init( &tmp );
if( expand_string( nxt_completion,
if( expand_string( 0,
nxt_completion,
&tmp,
ACCEPT_INCOMPLETE |
EXECUTABLES_ONLY ) != EXPAND_ERROR )
@ -1285,7 +1279,8 @@ static void complete_cmd( const wchar_t *cmd,
al_init( &tmp );
if( expand_string( nxt_completion,
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) );
}
/**

13
event.c
View file

@ -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
{
@ -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 )

1
exec.c
View file

@ -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

View file

@ -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,7 +558,9 @@ static int find_process( const wchar_t *proc,
continue;
}
signal_block();
fgetws2( &cmd, &sz, cmdfile );
signal_unblock();
fclose( cmdfile );
}
@ -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;
}

View file

@ -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.

View file

@ -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 );

View file

@ -18,7 +18,6 @@
typedef struct halloc
{
array_list_t children;
array_list_t hchildren;
long long data[0];
}
halloc_t;
@ -31,7 +30,6 @@ 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 );
@ -44,35 +42,39 @@ void *halloc( void *context, size_t size )
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; 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 );
free(me);
}

View file

@ -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

69
halloc_util.c Normal file
View file

@ -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;
}

29
halloc_util.h Normal file
View file

@ -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

View file

@ -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.

View file

@ -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()

View file

@ -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;

13
main.c
View file

@ -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
@ -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;

View file

@ -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();

View file

@ -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

View file

@ -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;
}
}

View file

@ -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

112
parser.c
View file

@ -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
@ -361,7 +362,6 @@ void parser_push_block( int type )
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 );
@ -748,7 +740,6 @@ wchar_t *get_filename( const wchar_t *cmd )
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,7 +970,6 @@ int eval_args( const wchar_t *line, array_list_t *args )
do_loop=0;
break;
}
}
@ -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,18 +1634,17 @@ 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 )
@ -1663,7 +1654,6 @@ static int parse_job( process_t *p,
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,7 +1700,6 @@ 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;
}
@ -1720,6 +1707,9 @@ static int parse_job( process_t *p,
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;
}

1
proc.c
View file

@ -109,6 +109,7 @@ void proc_init()
sb_init( &event_status );
}
/**
Remove job from list of jobs
*/

View file

@ -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;
if( !block_count )
{
sigfillset( &chldset );
sigprocmask(SIG_BLOCK, &chldset, 0);
}
block_count++;
}
void signal_unblock()
{
sigset_t chldset;
block_count--;
if( !block_count )
{
sigfillset( &chldset );
sigprocmask(SIG_UNBLOCK, &chldset, 0);
}
}

View file

@ -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

View file

@ -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();