mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 21:44:16 +00:00
Add the possibility for functions which do not shadow the arguments of the calling function
darcs-hash:20070422221033-ac50b-d9544c87d0ddab10f7f503b5a1707292f266efe4.gz
This commit is contained in:
parent
2b7535bb51
commit
ee94424b0f
6 changed files with 105 additions and 81 deletions
62
builtin.c
62
builtin.c
|
@ -1084,16 +1084,6 @@ static int builtin_functions( wchar_t **argv )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct function_data
|
|
||||||
{
|
|
||||||
wchar_t *name;
|
|
||||||
wchar_t *description;
|
|
||||||
array_list_t *events;
|
|
||||||
array_list_t *named_arguments;
|
|
||||||
}
|
|
||||||
function_data_t;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The function builtin, used for providing subroutines.
|
The function builtin, used for providing subroutines.
|
||||||
|
@ -1108,7 +1098,7 @@ static int builtin_function( wchar_t **argv )
|
||||||
int i;
|
int i;
|
||||||
array_list_t *named_arguments=0;
|
array_list_t *named_arguments=0;
|
||||||
wchar_t *name = 0;
|
wchar_t *name = 0;
|
||||||
|
int shadows = 1;
|
||||||
|
|
||||||
woptind=0;
|
woptind=0;
|
||||||
|
|
||||||
|
@ -1146,6 +1136,10 @@ static int builtin_function( wchar_t **argv )
|
||||||
L"argument-names", no_argument, 0, 'a'
|
L"argument-names", no_argument, 0, 'a'
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
{
|
||||||
|
L"no-scope-shadowing", no_argument, 0, 'S'
|
||||||
|
}
|
||||||
|
,
|
||||||
{
|
{
|
||||||
0, 0, 0, 0
|
0, 0, 0, 0
|
||||||
}
|
}
|
||||||
|
@ -1158,7 +1152,7 @@ static int builtin_function( wchar_t **argv )
|
||||||
|
|
||||||
int opt = wgetopt_long( argc,
|
int opt = wgetopt_long( argc,
|
||||||
argv,
|
argv,
|
||||||
L"d:s:j:p:v:ha",
|
L"d:s:j:p:v:haS",
|
||||||
long_options,
|
long_options,
|
||||||
&opt_index );
|
&opt_index );
|
||||||
if( opt == -1 )
|
if( opt == -1 )
|
||||||
|
@ -1312,7 +1306,10 @@ static int builtin_function( wchar_t **argv )
|
||||||
named_arguments = al_halloc( current_block );
|
named_arguments = al_halloc( current_block );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
shadows = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
builtin_print_help( argv[0], sb_out );
|
builtin_print_help( argv[0], sb_out );
|
||||||
return STATUS_BUILTIN_OK;
|
return STATUS_BUILTIN_OK;
|
||||||
|
@ -1431,6 +1428,7 @@ static int builtin_function( wchar_t **argv )
|
||||||
d->description=desc?halloc_wcsdup( current_block, desc):0;
|
d->description=desc?halloc_wcsdup( current_block, desc):0;
|
||||||
d->events = events;
|
d->events = events;
|
||||||
d->named_arguments = named_arguments;
|
d->named_arguments = named_arguments;
|
||||||
|
d->shadows = shadows;
|
||||||
|
|
||||||
for( i=0; i<al_get_count( events ); i++ )
|
for( i=0; i<al_get_count( events ); i++ )
|
||||||
{
|
{
|
||||||
|
@ -2691,31 +2689,6 @@ static int builtin_begin( wchar_t **argv )
|
||||||
return proc_get_last_status();
|
return proc_get_last_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Define the function specified by the function_data_t structure.
|
|
||||||
*/
|
|
||||||
static void builtin_end_add_function_def( function_data_t *d )
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
Copy the text from the beginning of the function
|
|
||||||
until the end command and use as the new definition
|
|
||||||
for the specified function
|
|
||||||
*/
|
|
||||||
|
|
||||||
wchar_t *def = wcsndup( parser_get_buffer()+current_block->tok_pos,
|
|
||||||
parser_get_job_pos()-current_block->tok_pos );
|
|
||||||
|
|
||||||
function_add( d->name,
|
|
||||||
def,
|
|
||||||
d->description,
|
|
||||||
d->events,
|
|
||||||
d->named_arguments );
|
|
||||||
|
|
||||||
free( def );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Builtin for ending a block of code, such as a for-loop or an if statement.
|
Builtin for ending a block of code, such as a for-loop or an if statement.
|
||||||
|
@ -2801,7 +2774,18 @@ static int builtin_end( wchar_t **argv )
|
||||||
|
|
||||||
if( d )
|
if( d )
|
||||||
{
|
{
|
||||||
builtin_end_add_function_def( d );
|
/**
|
||||||
|
Copy the text from the beginning of the function
|
||||||
|
until the end command and use as the new definition
|
||||||
|
for the specified function
|
||||||
|
*/
|
||||||
|
|
||||||
|
wchar_t *def = wcsndup( parser_get_buffer()+current_block->tok_pos,
|
||||||
|
parser_get_job_pos()-current_block->tok_pos );
|
||||||
|
d->definition = def;
|
||||||
|
|
||||||
|
function_add( d );
|
||||||
|
free( def );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
4
exec.c
4
exec.c
|
@ -994,6 +994,7 @@ void exec( job_t *j )
|
||||||
const wchar_t * orig_def;
|
const wchar_t * orig_def;
|
||||||
wchar_t * def=0;
|
wchar_t * def=0;
|
||||||
array_list_t *named_arguments;
|
array_list_t *named_arguments;
|
||||||
|
int shadows;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1005,6 +1006,7 @@ void exec( job_t *j )
|
||||||
signal_unblock();
|
signal_unblock();
|
||||||
orig_def = function_get_definition( p->argv[0] );
|
orig_def = function_get_definition( p->argv[0] );
|
||||||
named_arguments = function_get_named_arguments( p->argv[0] );
|
named_arguments = function_get_named_arguments( p->argv[0] );
|
||||||
|
shadows = function_get_shadows( p->argv[0] );
|
||||||
|
|
||||||
signal_block();
|
signal_block();
|
||||||
|
|
||||||
|
@ -1018,7 +1020,7 @@ void exec( job_t *j )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser_push_block( FUNCTION_CALL );
|
parser_push_block( shadows?FUNCTION_CALL:FUNCTION_CALL_NO_SHADOW );
|
||||||
|
|
||||||
current_block->param2.function_call_process = p;
|
current_block->param2.function_call_process = p;
|
||||||
current_block->param1.function_call_name = halloc_register( current_block, wcsdup( p->argv[0] ) );
|
current_block->param1.function_call_name = halloc_register( current_block, wcsdup( p->argv[0] ) );
|
||||||
|
|
84
function.c
84
function.c
|
@ -60,8 +60,10 @@ typedef struct
|
||||||
Flag for specifying that this function was automatically loaded
|
Flag for specifying that this function was automatically loaded
|
||||||
*/
|
*/
|
||||||
int is_autoload;
|
int is_autoload;
|
||||||
|
|
||||||
|
int shadows;
|
||||||
}
|
}
|
||||||
function_data_t;
|
function_internal_data_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Table containing all functions
|
Table containing all functions
|
||||||
|
@ -83,8 +85,8 @@ static int load( const wchar_t *name )
|
||||||
{
|
{
|
||||||
int was_autoload = is_autoload;
|
int was_autoload = is_autoload;
|
||||||
int res;
|
int res;
|
||||||
function_data_t *data;
|
function_internal_data_t *data;
|
||||||
data = (function_data_t *)hash_get( &function, name );
|
data = (function_internal_data_t *)hash_get( &function, name );
|
||||||
if( data && !data->is_autoload )
|
if( data && !data->is_autoload )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -165,46 +167,43 @@ void function_destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void function_add( const wchar_t *name,
|
void function_add( function_data_t *data )
|
||||||
const wchar_t *val,
|
|
||||||
const wchar_t *desc,
|
|
||||||
array_list_t *events,
|
|
||||||
array_list_t *named_arguments )
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
wchar_t *cmd_end;
|
wchar_t *cmd_end;
|
||||||
function_data_t *d;
|
function_internal_data_t *d;
|
||||||
|
|
||||||
CHECK( name, );
|
CHECK( data->name, );
|
||||||
CHECK( val, );
|
CHECK( data->definition, );
|
||||||
|
|
||||||
function_remove( name );
|
function_remove( data->name );
|
||||||
|
|
||||||
d = halloc( 0, sizeof( function_data_t ) );
|
d = halloc( 0, sizeof( function_internal_data_t ) );
|
||||||
d->definition_offset = parse_util_lineno( parser_get_buffer(), current_block->tok_pos )-1;
|
d->definition_offset = parse_util_lineno( parser_get_buffer(), current_block->tok_pos )-1;
|
||||||
d->cmd = halloc_wcsdup( d, val );
|
d->cmd = halloc_wcsdup( d, data->definition );
|
||||||
|
|
||||||
if( named_arguments )
|
if( data->named_arguments )
|
||||||
{
|
{
|
||||||
d->named_arguments = al_halloc( d );
|
d->named_arguments = al_halloc( d );
|
||||||
|
|
||||||
for( i=0; i<al_get_count( named_arguments ); i++ )
|
for( i=0; i<al_get_count( data->named_arguments ); i++ )
|
||||||
{
|
{
|
||||||
al_push( d->named_arguments, halloc_wcsdup( d, (wchar_t *)al_get( named_arguments, i ) ) );
|
al_push( d->named_arguments, halloc_wcsdup( d, (wchar_t *)al_get( data->named_arguments, i ) ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_end = d->cmd + wcslen(d->cmd)-1;
|
cmd_end = d->cmd + wcslen(d->cmd)-1;
|
||||||
|
|
||||||
d->desc = desc?halloc_wcsdup( d, desc ):0;
|
d->desc = data->description?halloc_wcsdup( d, data->description ):0;
|
||||||
d->definition_file = intern(reader_current_filename());
|
d->definition_file = intern(reader_current_filename());
|
||||||
d->is_autoload = is_autoload;
|
d->is_autoload = is_autoload;
|
||||||
|
d->shadows = data->shadows;
|
||||||
hash_put( &function, intern(name), d );
|
|
||||||
|
|
||||||
for( i=0; i<al_get_count( events ); i++ )
|
hash_put( &function, intern(data->name), d );
|
||||||
|
|
||||||
|
for( i=0; i<al_get_count( data->events ); i++ )
|
||||||
{
|
{
|
||||||
event_add_handler( (event_t *)al_get( events, i ) );
|
event_add_handler( (event_t *)al_get( data->events, i ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -225,7 +224,7 @@ void function_remove( const wchar_t *name )
|
||||||
{
|
{
|
||||||
void *key;
|
void *key;
|
||||||
void *dv;
|
void *dv;
|
||||||
function_data_t *d;
|
function_internal_data_t *d;
|
||||||
event_t ev;
|
event_t ev;
|
||||||
|
|
||||||
CHECK( name, );
|
CHECK( name, );
|
||||||
|
@ -235,7 +234,7 @@ void function_remove( const wchar_t *name )
|
||||||
&key,
|
&key,
|
||||||
&dv );
|
&dv );
|
||||||
|
|
||||||
d=(function_data_t *)dv;
|
d=(function_internal_data_t *)dv;
|
||||||
|
|
||||||
if( !key )
|
if( !key )
|
||||||
return;
|
return;
|
||||||
|
@ -259,12 +258,12 @@ void function_remove( const wchar_t *name )
|
||||||
|
|
||||||
const wchar_t *function_get_definition( const wchar_t *name )
|
const wchar_t *function_get_definition( const wchar_t *name )
|
||||||
{
|
{
|
||||||
function_data_t *data;
|
function_internal_data_t *data;
|
||||||
|
|
||||||
CHECK( name, 0 );
|
CHECK( name, 0 );
|
||||||
|
|
||||||
load( name );
|
load( name );
|
||||||
data = (function_data_t *)hash_get( &function, name );
|
data = (function_internal_data_t *)hash_get( &function, name );
|
||||||
if( data == 0 )
|
if( data == 0 )
|
||||||
return 0;
|
return 0;
|
||||||
return data->cmd;
|
return data->cmd;
|
||||||
|
@ -272,26 +271,39 @@ const wchar_t *function_get_definition( const wchar_t *name )
|
||||||
|
|
||||||
array_list_t *function_get_named_arguments( const wchar_t *name )
|
array_list_t *function_get_named_arguments( const wchar_t *name )
|
||||||
{
|
{
|
||||||
function_data_t *data;
|
function_internal_data_t *data;
|
||||||
|
|
||||||
CHECK( name, 0 );
|
CHECK( name, 0 );
|
||||||
|
|
||||||
load( name );
|
load( name );
|
||||||
data = (function_data_t *)hash_get( &function, name );
|
data = (function_internal_data_t *)hash_get( &function, name );
|
||||||
if( data == 0 )
|
if( data == 0 )
|
||||||
return 0;
|
return 0;
|
||||||
return data->named_arguments;
|
return data->named_arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int function_get_shadows( const wchar_t *name )
|
||||||
|
{
|
||||||
|
function_internal_data_t *data;
|
||||||
|
|
||||||
|
CHECK( name, 0 );
|
||||||
|
|
||||||
|
load( name );
|
||||||
|
data = (function_internal_data_t *)hash_get( &function, name );
|
||||||
|
if( data == 0 )
|
||||||
|
return 0;
|
||||||
|
return data->shadows;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const wchar_t *function_get_desc( const wchar_t *name )
|
const wchar_t *function_get_desc( const wchar_t *name )
|
||||||
{
|
{
|
||||||
function_data_t *data;
|
function_internal_data_t *data;
|
||||||
|
|
||||||
CHECK( name, 0 );
|
CHECK( name, 0 );
|
||||||
|
|
||||||
load( name );
|
load( name );
|
||||||
data = (function_data_t *)hash_get( &function, name );
|
data = (function_internal_data_t *)hash_get( &function, name );
|
||||||
if( data == 0 )
|
if( data == 0 )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -300,13 +312,13 @@ const wchar_t *function_get_desc( const wchar_t *name )
|
||||||
|
|
||||||
void function_set_desc( const wchar_t *name, const wchar_t *desc )
|
void function_set_desc( const wchar_t *name, const wchar_t *desc )
|
||||||
{
|
{
|
||||||
function_data_t *data;
|
function_internal_data_t *data;
|
||||||
|
|
||||||
CHECK( name, );
|
CHECK( name, );
|
||||||
CHECK( desc, );
|
CHECK( desc, );
|
||||||
|
|
||||||
load( name );
|
load( name );
|
||||||
data = (function_data_t *)hash_get( &function, name );
|
data = (function_internal_data_t *)hash_get( &function, name );
|
||||||
if( data == 0 )
|
if( data == 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -377,11 +389,11 @@ void function_get_names( array_list_t *list, int get_hidden )
|
||||||
|
|
||||||
const wchar_t *function_get_definition_file( const wchar_t *name )
|
const wchar_t *function_get_definition_file( const wchar_t *name )
|
||||||
{
|
{
|
||||||
function_data_t *data;
|
function_internal_data_t *data;
|
||||||
|
|
||||||
CHECK( name, 0 );
|
CHECK( name, 0 );
|
||||||
|
|
||||||
data = (function_data_t *)hash_get( &function, name );
|
data = (function_internal_data_t *)hash_get( &function, name );
|
||||||
if( data == 0 )
|
if( data == 0 )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -391,11 +403,11 @@ const wchar_t *function_get_definition_file( const wchar_t *name )
|
||||||
|
|
||||||
int function_get_definition_offset( const wchar_t *name )
|
int function_get_definition_offset( const wchar_t *name )
|
||||||
{
|
{
|
||||||
function_data_t *data;
|
function_internal_data_t *data;
|
||||||
|
|
||||||
CHECK( name, -1 );
|
CHECK( name, -1 );
|
||||||
|
|
||||||
data = (function_data_t *)hash_get( &function, name );
|
data = (function_internal_data_t *)hash_get( &function, name );
|
||||||
if( data == 0 )
|
if( data == 0 )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
26
function.h
26
function.h
|
@ -14,6 +14,21 @@
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Structure describing a function
|
||||||
|
*/
|
||||||
|
typedef struct function_data
|
||||||
|
{
|
||||||
|
wchar_t *name;
|
||||||
|
wchar_t *description;
|
||||||
|
wchar_t *definition;
|
||||||
|
array_list_t *events;
|
||||||
|
array_list_t *named_arguments;
|
||||||
|
int shadows;
|
||||||
|
}
|
||||||
|
function_data_t;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize function data
|
Initialize function data
|
||||||
*/
|
*/
|
||||||
|
@ -28,11 +43,7 @@ void function_destroy();
|
||||||
Add an function. The parameters values are copied and should be
|
Add an function. The parameters values are copied and should be
|
||||||
freed by the caller.
|
freed by the caller.
|
||||||
*/
|
*/
|
||||||
void function_add( const wchar_t *name,
|
void function_add( function_data_t *data );
|
||||||
const wchar_t *val,
|
|
||||||
const wchar_t *desc,
|
|
||||||
array_list_t *events,
|
|
||||||
array_list_t *named_arguments );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Remove the function with the specified name.
|
Remove the function with the specified name.
|
||||||
|
@ -92,4 +103,9 @@ int function_get_definition_offset( const wchar_t *name );
|
||||||
*/
|
*/
|
||||||
array_list_t *function_get_named_arguments( const wchar_t *name );
|
array_list_t *function_get_named_arguments( const wchar_t *name );
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns whether this function shadows variables of the underlying function
|
||||||
|
*/
|
||||||
|
int function_get_shadows( const wchar_t *name );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
9
parser.c
9
parser.c
|
@ -213,6 +213,11 @@ The fish parser. Contains functions for parsing and evaluating code.
|
||||||
*/
|
*/
|
||||||
#define FUNCTION_CALL_BLOCK N_( L"function invocation block" )
|
#define FUNCTION_CALL_BLOCK N_( L"function invocation block" )
|
||||||
|
|
||||||
|
/**
|
||||||
|
Function invocation block description
|
||||||
|
*/
|
||||||
|
#define FUNCTION_CALL_NO_SHADOW_BLOCK N_( L"function invocation block with no variable shadowing" )
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Switch block description
|
Switch block description
|
||||||
|
@ -309,6 +314,10 @@ const static struct block_lookup_entry block_lookup[]=
|
||||||
FUNCTION_CALL, 0, FUNCTION_CALL_BLOCK
|
FUNCTION_CALL, 0, FUNCTION_CALL_BLOCK
|
||||||
}
|
}
|
||||||
,
|
,
|
||||||
|
{
|
||||||
|
FUNCTION_CALL_NO_SHADOW, 0, FUNCTION_CALL_NO_SHADOW_BLOCK
|
||||||
|
}
|
||||||
|
,
|
||||||
{
|
{
|
||||||
SWITCH, L"switch", SWITCH_BLOCK
|
SWITCH, L"switch", SWITCH_BLOCK
|
||||||
}
|
}
|
||||||
|
|
1
parser.h
1
parser.h
|
@ -120,6 +120,7 @@ enum block_type
|
||||||
IF, /**< If block */
|
IF, /**< If block */
|
||||||
FUNCTION_DEF, /**< Function definition block */
|
FUNCTION_DEF, /**< Function definition block */
|
||||||
FUNCTION_CALL, /**< Function invocation block */
|
FUNCTION_CALL, /**< Function invocation block */
|
||||||
|
FUNCTION_CALL_NO_SHADOW, /**< Function invocation block with no variable shadowing */
|
||||||
SWITCH, /**< Switch block */
|
SWITCH, /**< Switch block */
|
||||||
FAKE, /**< Fake block */
|
FAKE, /**< Fake block */
|
||||||
SUBST, /**< Command substitution scope */
|
SUBST, /**< Command substitution scope */
|
||||||
|
|
Loading…
Reference in a new issue