mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Initial blocking implementation
darcs-hash:20051211222101-ac50b-6e11220bd608187fbb32a0313b5b73dbdc8354fc.gz
This commit is contained in:
parent
2cac04850b
commit
1d69e70b7a
11 changed files with 390 additions and 68 deletions
14
Makefile.in
14
Makefile.in
|
@ -79,13 +79,13 @@ MIME_OBJS := mimedb.o xdgmimealias.o xdgmime.o xdgmimeglob.o \
|
||||||
|
|
||||||
BUILTIN_DOC_SRC := doc_src/source.txt doc_src/and.txt \
|
BUILTIN_DOC_SRC := doc_src/source.txt doc_src/and.txt \
|
||||||
doc_src/begin.txt doc_src/bg.txt doc_src/bind.txt \
|
doc_src/begin.txt doc_src/bg.txt doc_src/bind.txt \
|
||||||
doc_src/break.txt doc_src/builtin.txt doc_src/case.txt \
|
doc_src/block.txt doc_src/break.txt doc_src/builtin.txt \
|
||||||
doc_src/cd.txt doc_src/command.txt doc_src/commandline.txt \
|
doc_src/case.txt doc_src/cd.txt doc_src/command.txt \
|
||||||
doc_src/complete.txt doc_src/continue.txt doc_src/else.txt \
|
doc_src/commandline.txt doc_src/complete.txt doc_src/continue.txt \
|
||||||
doc_src/end.txt doc_src/eval.txt doc_src/exec.txt doc_src/exit.txt \
|
doc_src/else.txt doc_src/end.txt doc_src/eval.txt doc_src/exec.txt \
|
||||||
doc_src/fg.txt doc_src/for.txt doc_src/function.txt \
|
doc_src/exit.txt doc_src/fg.txt doc_src/for.txt \
|
||||||
doc_src/functions.txt doc_src/if.txt doc_src/jobs.txt \
|
doc_src/function.txt doc_src/functions.txt doc_src/if.txt \
|
||||||
doc_src/not.txt doc_src/or.txt doc_src/random.txt \
|
doc_src/jobs.txt doc_src/not.txt doc_src/or.txt doc_src/random.txt \
|
||||||
doc_src/return.txt doc_src/read.txt doc_src/set.txt \
|
doc_src/return.txt doc_src/read.txt doc_src/set.txt \
|
||||||
doc_src/status.txt doc_src/switch.txt doc_src/ulimit.txt \
|
doc_src/status.txt doc_src/switch.txt doc_src/ulimit.txt \
|
||||||
doc_src/while.txt
|
doc_src/while.txt
|
||||||
|
|
182
builtin.c
182
builtin.c
|
@ -244,6 +244,173 @@ static int builtin_bind( wchar_t **argv )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The block builtin, used for temporarily blocking events
|
||||||
|
*/
|
||||||
|
static int builtin_block( wchar_t **argv )
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
UNSET,
|
||||||
|
GLOBAL,
|
||||||
|
LOCAL,
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int scope=UNSET;
|
||||||
|
|
||||||
|
int erase = 0;
|
||||||
|
|
||||||
|
int argc=builtin_count_args( argv );
|
||||||
|
|
||||||
|
int type = (1<<EVENT_ANY);
|
||||||
|
|
||||||
|
|
||||||
|
woptind=0;
|
||||||
|
|
||||||
|
const static struct woption
|
||||||
|
long_options[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
L"erase", no_argument, 0, 'e'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
L"local", no_argument, 0, 'l'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
L"global", no_argument, 0, 'g'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
L"help", no_argument, 0, 'h'
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
0, 0, 0, 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
while( 1 )
|
||||||
|
{
|
||||||
|
int opt_index = 0;
|
||||||
|
|
||||||
|
int opt = wgetopt_long( argc,
|
||||||
|
argv,
|
||||||
|
L"elgh",
|
||||||
|
long_options,
|
||||||
|
&opt_index );
|
||||||
|
if( opt == -1 )
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch( opt )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if(long_options[opt_index].flag != 0)
|
||||||
|
break;
|
||||||
|
sb_append2( sb_err,
|
||||||
|
argv[0],
|
||||||
|
BUILTIN_ERR_UNKNOWN,
|
||||||
|
L" ",
|
||||||
|
long_options[opt_index].name,
|
||||||
|
L"\n",
|
||||||
|
(void *)0);
|
||||||
|
builtin_print_help( argv[0], sb_err );
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
case 'h':
|
||||||
|
builtin_print_help( argv[0], sb_err );
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 'g':
|
||||||
|
scope = GLOBAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
scope = LOCAL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
erase = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
builtin_print_help( argv[0], sb_err );
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if( erase )
|
||||||
|
{
|
||||||
|
if( scope != UNSET )
|
||||||
|
{
|
||||||
|
sb_printf( sb_err, L"%ls: Can not specify scope when removing block\n", argv[0] );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( !global_event_block )
|
||||||
|
{
|
||||||
|
sb_printf( sb_err, L"%ls: No blocks defined\n", argv[0] );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_block_t *eb = global_event_block;
|
||||||
|
global_event_block = eb->next;
|
||||||
|
free( eb );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block_t *block=current_block;
|
||||||
|
|
||||||
|
event_block_t *eb = malloc( sizeof( event_block_t ) );
|
||||||
|
|
||||||
|
if( !eb )
|
||||||
|
die_mem();
|
||||||
|
|
||||||
|
eb->type = type;
|
||||||
|
|
||||||
|
switch( scope )
|
||||||
|
{
|
||||||
|
case LOCAL:
|
||||||
|
{
|
||||||
|
if( !block->outer )
|
||||||
|
block=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GLOBAL:
|
||||||
|
{
|
||||||
|
block=0;
|
||||||
|
}
|
||||||
|
case UNSET:
|
||||||
|
{
|
||||||
|
while( block && block->type != FUNCTION_CALL )
|
||||||
|
block = block->outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( block )
|
||||||
|
{
|
||||||
|
eb->next = block->first_event_block;
|
||||||
|
block->first_event_block = eb;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
eb->next = global_event_block;
|
||||||
|
global_event_block=eb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The builtin builtin, used for given builtins precedence over functions. Mostly handled by the parser. All this code does is some additional operational modes, such as printing a list of all builtins.
|
The builtin builtin, used for given builtins precedence over functions. Mostly handled by the parser. All this code does is some additional operational modes, such as printing a list of all builtins.
|
||||||
|
@ -838,7 +1005,7 @@ static int builtin_function( wchar_t **argv )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = malloc( sizeof(event_t));
|
e = calloc( 1, sizeof(event_t));
|
||||||
if( !e )
|
if( !e )
|
||||||
die_mem();
|
die_mem();
|
||||||
e->type = EVENT_SIGNAL;
|
e->type = EVENT_SIGNAL;
|
||||||
|
@ -862,7 +1029,7 @@ static int builtin_function( wchar_t **argv )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = malloc( sizeof(event_t));
|
e = calloc( 1, sizeof(event_t));
|
||||||
if( !e )
|
if( !e )
|
||||||
die_mem();
|
die_mem();
|
||||||
e->type = EVENT_VARIABLE;
|
e->type = EVENT_VARIABLE;
|
||||||
|
@ -879,7 +1046,7 @@ static int builtin_function( wchar_t **argv )
|
||||||
wchar_t *end;
|
wchar_t *end;
|
||||||
event_t *e;
|
event_t *e;
|
||||||
|
|
||||||
e = malloc( sizeof(event_t));
|
e = calloc( 1, sizeof(event_t));
|
||||||
if( !e )
|
if( !e )
|
||||||
die_mem();
|
die_mem();
|
||||||
|
|
||||||
|
@ -2850,6 +3017,7 @@ void builtin_init()
|
||||||
hash_init( &builtin, &hash_wcs_func, &hash_wcs_cmp );
|
hash_init( &builtin, &hash_wcs_func, &hash_wcs_cmp );
|
||||||
|
|
||||||
hash_put( &builtin, L"exit", (void*) &builtin_exit );
|
hash_put( &builtin, L"exit", (void*) &builtin_exit );
|
||||||
|
hash_put( &builtin, L"block", (void*) &builtin_block );
|
||||||
hash_put( &builtin, L"builtin", (void*) &builtin_builtin );
|
hash_put( &builtin, L"builtin", (void*) &builtin_builtin );
|
||||||
hash_put( &builtin, L"cd", (void*) &builtin_cd );
|
hash_put( &builtin, L"cd", (void*) &builtin_cd );
|
||||||
hash_put( &builtin, L"function", (void*) &builtin_function );
|
hash_put( &builtin, L"function", (void*) &builtin_function );
|
||||||
|
@ -2899,6 +3067,7 @@ void builtin_init()
|
||||||
|
|
||||||
intern_static( L"exit" );
|
intern_static( L"exit" );
|
||||||
intern_static( L"builtin" );
|
intern_static( L"builtin" );
|
||||||
|
intern_static( L"block" );
|
||||||
intern_static( L"cd" );
|
intern_static( L"cd" );
|
||||||
intern_static( L"function" );
|
intern_static( L"function" );
|
||||||
intern_static( L"functions" );
|
intern_static( L"functions" );
|
||||||
|
@ -3026,11 +3195,13 @@ const wchar_t *builtin_get_desc( const wchar_t *b )
|
||||||
|
|
||||||
hash_init( desc, &hash_wcs_func, &hash_wcs_cmp );
|
hash_init( desc, &hash_wcs_func, &hash_wcs_cmp );
|
||||||
|
|
||||||
hash_put( desc, L"exit", L"Exit the shell" );
|
hash_put( desc, L"block", L"Temporarily block delivery of events" );
|
||||||
|
hash_put( desc, L"builtin", L"Run a builtin command" );
|
||||||
|
hash_put( desc, L"complete", L"Edit command specific completions" );
|
||||||
hash_put( desc, L"cd", L"Change working directory" );
|
hash_put( desc, L"cd", L"Change working directory" );
|
||||||
|
hash_put( desc, L"exit", L"Exit the shell" );
|
||||||
hash_put( desc, L"function", L"Define a new function" );
|
hash_put( desc, L"function", L"Define a new function" );
|
||||||
hash_put( desc, L"functions", L"List or remove functions" );
|
hash_put( desc, L"functions", L"List or remove functions" );
|
||||||
hash_put( desc, L"complete", L"Edit command specific completions" );
|
|
||||||
hash_put( desc, L"end", L"End a block of commands" );
|
hash_put( desc, L"end", L"End a block of commands" );
|
||||||
hash_put( desc, L"else", L"Evaluate block if condition is false" );
|
hash_put( desc, L"else", L"Evaluate block if condition is false" );
|
||||||
hash_put( desc, L"eval", L"Evaluate parameters as a command" );
|
hash_put( desc, L"eval", L"Evaluate parameters as a command" );
|
||||||
|
@ -3047,7 +3218,6 @@ const wchar_t *builtin_get_desc( const wchar_t *b )
|
||||||
hash_put( desc, L"commandline", L"Set the commandline" );
|
hash_put( desc, L"commandline", L"Set the commandline" );
|
||||||
hash_put( desc, L"switch", L"Conditionally execute a block of commands" );
|
hash_put( desc, L"switch", L"Conditionally execute a block of commands" );
|
||||||
hash_put( desc, L"case", L"Conditionally execute a block of commands" );
|
hash_put( desc, L"case", L"Conditionally execute a block of commands" );
|
||||||
hash_put( desc, L"builtin", L"Run a builtin command" );
|
|
||||||
hash_put( desc, L"command", L"Run a program" );
|
hash_put( desc, L"command", L"Run a program" );
|
||||||
hash_put( desc, L"if", L"Conditionally execute a command" );
|
hash_put( desc, L"if", L"Conditionally execute a command" );
|
||||||
hash_put( desc, L"while", L"Perform a command multiple times" );
|
hash_put( desc, L"while", L"Perform a command multiple times" );
|
||||||
|
|
|
@ -682,6 +682,7 @@ builtins or shellscript functions, and can only be used inside fish.
|
||||||
- <a href="builtins.html#begin">begin</a>, execute a block of commands
|
- <a href="builtins.html#begin">begin</a>, execute a block of commands
|
||||||
- <a href="builtins.html#bind">bind</a>, change keyboard bindings
|
- <a href="builtins.html#bind">bind</a>, change keyboard bindings
|
||||||
- <a href="builtins.html#break">break</a>, stop the execution of a loop
|
- <a href="builtins.html#break">break</a>, stop the execution of a loop
|
||||||
|
- <a href="builtins.html#block">block</a>, Temporarily block delivery of events
|
||||||
- <a href="builtins.html#builtin">builtin</a>, execute a builtin command
|
- <a href="builtins.html#builtin">builtin</a>, execute a builtin command
|
||||||
- <a href="builtins.html#case">case</a>, conditionally execute a block of commands
|
- <a href="builtins.html#case">case</a>, conditionally execute a block of commands
|
||||||
- <a href="builtins.html#cd">cd</a>, change the current directory
|
- <a href="builtins.html#cd">cd</a>, change the current directory
|
||||||
|
@ -995,7 +996,10 @@ g++, javac, java, gcj, lpr, doxygen, whois, find)
|
||||||
- Check keybinding commands for output - if non has happened, don't repaint to reduce flicker
|
- Check keybinding commands for output - if non has happened, don't repaint to reduce flicker
|
||||||
- The jobs builtin should be able to give information on a specific job, such as the pids of the processes in the job
|
- The jobs builtin should be able to give information on a specific job, such as the pids of the processes in the job
|
||||||
- Syntax highlighting should mark cd to non-existing directories as an error
|
- Syntax highlighting should mark cd to non-existing directories as an error
|
||||||
|
- the code for printing the prompt should know about the most common escape sequences
|
||||||
|
- block builtin
|
||||||
|
- redo the jobs command
|
||||||
|
- wait shellscript
|
||||||
|
|
||||||
\subsection todo-possible Possible features
|
\subsection todo-possible Possible features
|
||||||
|
|
||||||
|
|
24
env.c
24
env.c
|
@ -236,7 +236,6 @@ static void universal_callback( int type,
|
||||||
|
|
||||||
if( str )
|
if( str )
|
||||||
{
|
{
|
||||||
array_list_t arg;
|
|
||||||
event_t ev;
|
event_t ev;
|
||||||
|
|
||||||
has_changed=1;
|
has_changed=1;
|
||||||
|
@ -245,12 +244,12 @@ static void universal_callback( int type,
|
||||||
ev.param1.variable=name;
|
ev.param1.variable=name;
|
||||||
ev.function_name=0;
|
ev.function_name=0;
|
||||||
|
|
||||||
al_init( &arg );
|
al_init( &ev.arguments );
|
||||||
al_push( &arg, L"VARIABLE" );
|
al_push( &ev.arguments, L"VARIABLE" );
|
||||||
al_push( &arg, str );
|
al_push( &ev.arguments, str );
|
||||||
al_push( &arg, name );
|
al_push( &ev.arguments, name );
|
||||||
event_fire( &ev, &arg );
|
event_fire( &ev );
|
||||||
al_destroy( &arg );
|
al_destroy( &ev.arguments );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,7 +488,6 @@ void env_set( const wchar_t *key,
|
||||||
int done=0;
|
int done=0;
|
||||||
|
|
||||||
event_t ev;
|
event_t ev;
|
||||||
array_list_t ev_list;
|
|
||||||
int is_universal = 0;
|
int is_universal = 0;
|
||||||
|
|
||||||
if( (var_mode & ENV_USER ) &&
|
if( (var_mode & ENV_USER ) &&
|
||||||
|
@ -669,14 +667,14 @@ void env_set( const wchar_t *key,
|
||||||
ev.param1.variable = key;
|
ev.param1.variable = key;
|
||||||
ev.function_name = 0;
|
ev.function_name = 0;
|
||||||
|
|
||||||
al_init( &ev_list );
|
al_init( &ev.arguments );
|
||||||
al_push( &ev_list, L"VARIABLE" );
|
al_push( &ev.arguments, L"VARIABLE" );
|
||||||
al_push( &ev_list, key );
|
al_push( &ev.arguments, key );
|
||||||
|
|
||||||
// debug( 1, L"env_set: fire events on variable %ls", key );
|
// debug( 1, L"env_set: fire events on variable %ls", key );
|
||||||
event_fire( &ev, &ev_list );
|
event_fire( &ev );
|
||||||
// debug( 1, L"env_set: return from event firing" );
|
// debug( 1, L"env_set: return from event firing" );
|
||||||
al_destroy( &ev_list );
|
al_destroy( &ev.arguments );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
135
event.c
135
event.c
|
@ -67,6 +67,12 @@ static array_list_t *events;
|
||||||
*/
|
*/
|
||||||
static array_list_t *killme;
|
static array_list_t *killme;
|
||||||
|
|
||||||
|
/**
|
||||||
|
List of events that have been sent but have not yet been delivered because they are blocked.
|
||||||
|
*/
|
||||||
|
static array_list_t *blocked;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Tests if one event instance matches the definition of a event
|
Tests if one event instance matches the definition of a event
|
||||||
class. If the class defines a function name, that will also be a
|
class. If the class defines a function name, that will also be a
|
||||||
|
@ -120,7 +126,7 @@ static int event_match( event_t *class, event_t *instance )
|
||||||
Create an identical copy of an event. Use deep copying, i.e. make
|
Create an identical copy of an event. Use deep copying, i.e. make
|
||||||
duplicates of any strings used as well.
|
duplicates of any strings used as well.
|
||||||
*/
|
*/
|
||||||
static event_t *event_copy( event_t *event )
|
static event_t *event_copy( event_t *event, int copy_arguments )
|
||||||
{
|
{
|
||||||
event_t *e = malloc( sizeof( event_t ) );
|
event_t *e = malloc( sizeof( event_t ) );
|
||||||
if( !e )
|
if( !e )
|
||||||
|
@ -133,12 +139,55 @@ static event_t *event_copy( event_t *event )
|
||||||
if( e->type == EVENT_VARIABLE )
|
if( e->type == EVENT_VARIABLE )
|
||||||
e->param1.variable = wcsdup( e->param1.variable );
|
e->param1.variable = wcsdup( e->param1.variable );
|
||||||
|
|
||||||
|
al_init( &e->arguments );
|
||||||
|
if( copy_arguments )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for( i=0; i<al_get_count( &event->arguments ); i++ )
|
||||||
|
{
|
||||||
|
al_push( &e->arguments, wcsdup( (wchar_t *)al_get( &event->arguments, i ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int event_is_blocked( event_t *e )
|
||||||
|
{
|
||||||
|
block_t *block;
|
||||||
|
event_block_t *eb;
|
||||||
|
|
||||||
|
for( block = current_block; block; block = block->outer )
|
||||||
|
{
|
||||||
|
for( eb = block->first_event_block; eb; eb=eb->next )
|
||||||
|
{
|
||||||
|
if( eb->type & (1<<EVENT_ANY ) )
|
||||||
|
return 1;
|
||||||
|
if( eb->type & (1<<e->type) )
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for( eb = global_event_block; eb; eb=eb->next )
|
||||||
|
{
|
||||||
|
if( eb->type & (1<<EVENT_ANY ) )
|
||||||
|
return 1;
|
||||||
|
if( eb->type & (1<<e->type) )
|
||||||
|
return 1;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void event_add_handler( event_t *event )
|
void event_add_handler( event_t *event )
|
||||||
{
|
{
|
||||||
event_t *e = event_copy( event );
|
event_t *e;
|
||||||
|
|
||||||
|
e = event_copy( event, 0 );
|
||||||
|
|
||||||
if( !events )
|
if( !events )
|
||||||
events = al_new();
|
events = al_new();
|
||||||
|
@ -268,7 +317,7 @@ static int event_is_killed( event_t *e )
|
||||||
matches' path. This means that nothing is allocated/initialized
|
matches' path. This means that nothing is allocated/initialized
|
||||||
unless that is needed.
|
unless that is needed.
|
||||||
*/
|
*/
|
||||||
static void event_fire_internal( event_t *event, array_list_t *arguments )
|
static void event_fire_internal( event_t *event )
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
string_buffer_t *b=0;
|
string_buffer_t *b=0;
|
||||||
|
@ -337,9 +386,9 @@ static void event_fire_internal( event_t *event, array_list_t *arguments )
|
||||||
|
|
||||||
sb_append( b, criterion->function_name );
|
sb_append( b, criterion->function_name );
|
||||||
|
|
||||||
for( j=0; j<al_get_count(arguments); j++ )
|
for( j=0; j<al_get_count(&event->arguments); j++ )
|
||||||
{
|
{
|
||||||
wchar_t *arg_esc = escape( (wchar_t *)al_get( arguments, j), 0 );
|
wchar_t *arg_esc = escape( (wchar_t *)al_get( &event->arguments, j), 0 );
|
||||||
sb_append( b, L" " );
|
sb_append( b, L" " );
|
||||||
sb_append( b, arg_esc );
|
sb_append( b, arg_esc );
|
||||||
free( arg_esc );
|
free( arg_esc );
|
||||||
|
@ -385,15 +434,42 @@ static void event_fire_internal( event_t *event, array_list_t *arguments )
|
||||||
/**
|
/**
|
||||||
Handle all pending signal events
|
Handle all pending signal events
|
||||||
*/
|
*/
|
||||||
static void event_fire_signal_events()
|
static void event_fire_delayed()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if( blocked && is_event==1)
|
||||||
|
{
|
||||||
|
array_list_t *new_blocked = 0;
|
||||||
|
|
||||||
|
for( i=0; i<al_get_count( blocked ); i++ )
|
||||||
|
{
|
||||||
|
event_t *e = (event_t *)al_get( blocked, i );
|
||||||
|
if( event_is_blocked( e ) )
|
||||||
|
{
|
||||||
|
if( !new_blocked )
|
||||||
|
new_blocked = al_new();
|
||||||
|
al_push( new_blocked, e );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event_fire_internal( e );
|
||||||
|
event_free( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
al_destroy( blocked );
|
||||||
|
free( blocked );
|
||||||
|
blocked = new_blocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
while( sig_list[active_list].count > 0 )
|
while( sig_list[active_list].count > 0 )
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
signal_list_t *lst;
|
signal_list_t *lst;
|
||||||
event_t e;
|
event_t e;
|
||||||
array_list_t a;
|
al_init( &e.arguments );
|
||||||
al_init( &a );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Switch signal lists
|
Switch signal lists
|
||||||
|
@ -421,17 +497,26 @@ static void event_fire_signal_events()
|
||||||
for( i=0; i<lst->count; i++ )
|
for( i=0; i<lst->count; i++ )
|
||||||
{
|
{
|
||||||
e.param1.signal = lst->signal[i];
|
e.param1.signal = lst->signal[i];
|
||||||
al_set( &a, 0, sig2wcs( e.param1.signal ) );
|
al_set( &e.arguments, 0, sig2wcs( e.param1.signal ) );
|
||||||
event_fire_internal( &e, &a );
|
if( event_is_blocked( &e ) )
|
||||||
|
{
|
||||||
|
if( !blocked )
|
||||||
|
blocked = al_new();
|
||||||
|
al_push( blocked, event_copy(&e, 1) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event_fire_internal( &e );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
al_destroy( &a );
|
al_destroy( &e.arguments );
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void event_fire( event_t *event, array_list_t *arguments )
|
void event_fire( event_t *event )
|
||||||
{
|
{
|
||||||
//int is_event_old = is_event;
|
//int is_event_old = is_event;
|
||||||
is_event++;
|
is_event++;
|
||||||
|
@ -452,10 +537,23 @@ void event_fire( event_t *event, array_list_t *arguments )
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
event_fire_signal_events();
|
|
||||||
|
event_fire_delayed();
|
||||||
|
|
||||||
if( event )
|
if( event )
|
||||||
event_fire_internal( event, arguments );
|
{
|
||||||
|
if( event_is_blocked( event ) )
|
||||||
|
{
|
||||||
|
if( !blocked )
|
||||||
|
blocked = al_new();
|
||||||
|
|
||||||
|
al_push( blocked, event_copy(event, 1) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
event_fire_internal( event );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
is_event--;// = is_event_old;
|
is_event--;// = is_event_old;
|
||||||
|
@ -487,9 +585,14 @@ void event_destroy()
|
||||||
|
|
||||||
void event_free( event_t *e )
|
void event_free( event_t *e )
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
When apropriate, we clear the argument vector
|
||||||
|
*/
|
||||||
|
al_foreach( &e->arguments, (void (*)(const void *))&free );
|
||||||
|
al_destroy( &e->arguments );
|
||||||
|
|
||||||
free( (void *)e->function_name );
|
free( (void *)e->function_name );
|
||||||
if( e->type == EVENT_VARIABLE )
|
if( e->type == EVENT_VARIABLE )
|
||||||
free( (void *)e->param1.variable );
|
free( (void *)e->param1.variable );
|
||||||
free( e );
|
free( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
event.h
15
event.h
|
@ -43,7 +43,8 @@ typedef struct
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
Signal number for signal-type events.Use EVENT_ANY_SIGNAL to match any signal
|
Signal number for signal-type events.Use EVENT_ANY_SIGNAL
|
||||||
|
to match any signal
|
||||||
*/
|
*/
|
||||||
int signal;
|
int signal;
|
||||||
/**
|
/**
|
||||||
|
@ -51,7 +52,8 @@ typedef struct
|
||||||
*/
|
*/
|
||||||
const wchar_t *variable;
|
const wchar_t *variable;
|
||||||
/**
|
/**
|
||||||
Process id for process-type events. Use EVENT_ANY_PID to match any pid.
|
Process id for process-type events. Use EVENT_ANY_PID to
|
||||||
|
match any pid.
|
||||||
*/
|
*/
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
/**
|
/**
|
||||||
|
@ -65,6 +67,13 @@ typedef struct
|
||||||
The name of the event handler function
|
The name of the event handler function
|
||||||
*/
|
*/
|
||||||
const wchar_t *function_name;
|
const wchar_t *function_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The argument list. Only used when sending a new event using
|
||||||
|
event_fire. In all other situations, the value of this variable
|
||||||
|
is ignored.
|
||||||
|
*/
|
||||||
|
array_list_t arguments;
|
||||||
}
|
}
|
||||||
event_t;
|
event_t;
|
||||||
|
|
||||||
|
@ -98,7 +107,7 @@ int event_get( event_t *criterion, array_list_t *out );
|
||||||
\param event the specific event whose handlers should fire
|
\param event the specific event whose handlers should fire
|
||||||
\param arguments the argument string to send to the event handler function
|
\param arguments the argument string to send to the event handler function
|
||||||
*/
|
*/
|
||||||
void event_fire( event_t *event, array_list_t *arguments );
|
void event_fire( event_t *event );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize the event-handling library
|
Initialize the event-handling library
|
||||||
|
|
2
input.c
2
input.c
|
@ -1270,7 +1270,7 @@ static int interrupt_handler()
|
||||||
/*
|
/*
|
||||||
Fire any pending events
|
Fire any pending events
|
||||||
*/
|
*/
|
||||||
event_fire( 0, 0 );
|
event_fire( 0 );
|
||||||
if( job_reap( 1 ) )
|
if( job_reap( 1 ) )
|
||||||
repaint();
|
repaint();
|
||||||
if( reader_interupted() )
|
if( reader_interupted() )
|
||||||
|
|
15
parser.c
15
parser.c
|
@ -111,6 +111,8 @@ The fish parser. Contains functions for parsing code.
|
||||||
/** Last error code */
|
/** Last error code */
|
||||||
int error_code;
|
int error_code;
|
||||||
|
|
||||||
|
event_block_t *global_event_block=0;
|
||||||
|
|
||||||
/** Position of last error */
|
/** Position of last error */
|
||||||
|
|
||||||
static int err_pos;
|
static int err_pos;
|
||||||
|
@ -194,7 +196,7 @@ int block_count( block_t *b )
|
||||||
|
|
||||||
void parser_push_block( int type )
|
void parser_push_block( int type )
|
||||||
{
|
{
|
||||||
block_t *new = malloc( sizeof( block_t ));
|
block_t *new = calloc( 1, sizeof( block_t ));
|
||||||
|
|
||||||
// debug( 2, L"Block push %ls %d\n", bl[type], block_count( current_block)+1 );
|
// debug( 2, L"Block push %ls %d\n", bl[type], block_count( current_block)+1 );
|
||||||
new->outer = current_block;
|
new->outer = current_block;
|
||||||
|
@ -230,6 +232,7 @@ void parser_push_block( int type )
|
||||||
void parser_pop_block()
|
void parser_pop_block()
|
||||||
{
|
{
|
||||||
// debug( 2, L"Block pop %ls %d\n", bl[current_block->type], block_count(current_block)-1 );
|
// debug( 2, L"Block pop %ls %d\n", bl[current_block->type], block_count(current_block)-1 );
|
||||||
|
event_block_t *eb, *eb_next;
|
||||||
|
|
||||||
if( (current_block->type != FUNCTION_DEF ) &&
|
if( (current_block->type != FUNCTION_DEF ) &&
|
||||||
(current_block->type != FAKE) &&
|
(current_block->type != FAKE) &&
|
||||||
|
@ -270,6 +273,12 @@ void parser_pop_block()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for( eb=current_block->first_event_block; eb; eb=eb_next )
|
||||||
|
{
|
||||||
|
eb_next = eb->next;
|
||||||
|
free(eb);
|
||||||
|
}
|
||||||
|
|
||||||
block_t *old = current_block;
|
block_t *old = current_block;
|
||||||
current_block = current_block->outer;
|
current_block = current_block->outer;
|
||||||
free( old );
|
free( old );
|
||||||
|
@ -1996,7 +2005,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
||||||
tok_init( current_tokenizer, cmd, 0 );
|
tok_init( current_tokenizer, cmd, 0 );
|
||||||
error_code = 0;
|
error_code = 0;
|
||||||
|
|
||||||
event_fire( 0, 0 );
|
event_fire( 0 );
|
||||||
|
|
||||||
while( tok_has_next( current_tokenizer ) &&
|
while( tok_has_next( current_tokenizer ) &&
|
||||||
!error_code &&
|
!error_code &&
|
||||||
|
@ -2004,7 +2013,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
||||||
!exit_status() )
|
!exit_status() )
|
||||||
{
|
{
|
||||||
eval_job( current_tokenizer );
|
eval_job( current_tokenizer );
|
||||||
event_fire( 0, 0 );
|
event_fire( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
int prev_block_type = current_block->type;
|
int prev_block_type = current_block->type;
|
||||||
|
|
34
parser.h
34
parser.h
|
@ -11,6 +11,27 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
|
typedef struct event_block
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
The types of events to block. This is interpreted as a bitset
|
||||||
|
whete the value is 1 for every bit corresponding to a blocked
|
||||||
|
event type. For example, if EVENT_VARIABLE type events should
|
||||||
|
be blocked, (type & 1<<EVENT_BLOCKED) should be set.
|
||||||
|
|
||||||
|
Note that EVENT_ANY can be used to specify any event.
|
||||||
|
*/
|
||||||
|
int type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
The next event_block struct
|
||||||
|
*/
|
||||||
|
struct event_block *next;
|
||||||
|
}
|
||||||
|
event_block_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
block_t represents a block of commands.
|
block_t represents a block of commands.
|
||||||
*/
|
*/
|
||||||
|
@ -21,12 +42,12 @@ typedef struct block
|
||||||
int tok_pos; /**< The start index of the block */
|
int tok_pos; /**< The start index of the block */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Status for the current loop block. Can be anu of the values from the loop_status enum.
|
Status for the current loop block. Can be any of the values from the loop_status enum.
|
||||||
*/
|
*/
|
||||||
int loop_status;
|
int loop_status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The log that is currently evaluated in the specified block.
|
The job that is currently evaluated in the specified block.
|
||||||
*/
|
*/
|
||||||
job_t *job;
|
job_t *job;
|
||||||
|
|
||||||
|
@ -68,7 +89,10 @@ typedef struct block
|
||||||
array_list_t *function_events;
|
array_list_t *function_events;
|
||||||
} param4;
|
} param4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Some naming confusion. This is a pointer to the first element in the list of all event blocks.
|
||||||
|
*/
|
||||||
|
event_block_t *first_event_block;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Next outer block
|
Next outer block
|
||||||
|
@ -159,6 +183,10 @@ enum parser_error
|
||||||
/** The current innermost block */
|
/** The current innermost block */
|
||||||
extern block_t *current_block;
|
extern block_t *current_block;
|
||||||
|
|
||||||
|
/** Global event blocks */
|
||||||
|
extern event_block_t *global_event_block;
|
||||||
|
|
||||||
|
|
||||||
/** The current error code */
|
/** The current error code */
|
||||||
extern int error_code;
|
extern int error_code;
|
||||||
|
|
||||||
|
|
25
proc.c
25
proc.c
|
@ -76,9 +76,10 @@ int proc_had_barrier;
|
||||||
pid_t proc_last_bg_pid = 0;
|
pid_t proc_last_bg_pid = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
List used to store arguments when firing events
|
The event variable used to send all process event
|
||||||
*/
|
*/
|
||||||
static array_list_t event_arg;
|
static event_t event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Stringbuffer used to create arguments when firing events
|
Stringbuffer used to create arguments when firing events
|
||||||
*/
|
*/
|
||||||
|
@ -91,7 +92,7 @@ static string_buffer_t event_status;
|
||||||
|
|
||||||
void proc_init()
|
void proc_init()
|
||||||
{
|
{
|
||||||
al_init( &event_arg );
|
al_init( &event.arguments );
|
||||||
sb_init( &event_pid );
|
sb_init( &event_pid );
|
||||||
sb_init( &event_status );
|
sb_init( &event_status );
|
||||||
}
|
}
|
||||||
|
@ -185,7 +186,7 @@ void job_free( job_t * j )
|
||||||
|
|
||||||
void proc_destroy()
|
void proc_destroy()
|
||||||
{
|
{
|
||||||
al_destroy( &event_arg );
|
al_destroy( &event.arguments );
|
||||||
sb_destroy( &event_pid );
|
sb_destroy( &event_pid );
|
||||||
sb_destroy( &event_status );
|
sb_destroy( &event_status );
|
||||||
while( first_job )
|
while( first_job )
|
||||||
|
@ -484,21 +485,21 @@ static void format_job_info( const job_t *j, const wchar_t *status )
|
||||||
|
|
||||||
void proc_fire_event( const wchar_t *msg, int type, pid_t pid, int status )
|
void proc_fire_event( const wchar_t *msg, int type, pid_t pid, int status )
|
||||||
{
|
{
|
||||||
static event_t ev;
|
|
||||||
|
|
||||||
ev.type=type;
|
event.type=type;
|
||||||
ev.param1.pid = pid;
|
event.param1.pid = pid;
|
||||||
|
|
||||||
al_push( &event_arg, msg );
|
al_push( &event.arguments, msg );
|
||||||
|
|
||||||
sb_printf( &event_pid, L"%d", pid );
|
sb_printf( &event_pid, L"%d", pid );
|
||||||
al_push( &event_arg, event_pid.buff );
|
al_push( &event.arguments, event_pid.buff );
|
||||||
|
|
||||||
sb_printf( &event_status, L"%d", status );
|
sb_printf( &event_status, L"%d", status );
|
||||||
al_push( &event_arg, event_status.buff );
|
al_push( &event.arguments, event_status.buff );
|
||||||
|
|
||||||
event_fire( &ev, &event_arg );
|
event_fire( &event );
|
||||||
al_truncate( &event_arg, 0 );
|
|
||||||
|
al_truncate( &event.arguments, 0 );
|
||||||
sb_clear( &event_pid );
|
sb_clear( &event_pid );
|
||||||
sb_clear( &event_status );
|
sb_clear( &event_status );
|
||||||
}
|
}
|
||||||
|
|
2
signal.c
2
signal.c
|
@ -305,7 +305,7 @@ static void default_handler(int signal, siginfo_t *info, void *context)
|
||||||
e.param1.signal = signal;
|
e.param1.signal = signal;
|
||||||
e.function_name=0;
|
e.function_name=0;
|
||||||
|
|
||||||
event_fire( &e, 0 );
|
event_fire( &e );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue