mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 05:13:10 +00:00
Optionally add type of block to the end builtin to verify block nesting correctness
darcs-hash:20060905204347-ac50b-d0f87a700e38cdff9787be827b0df90b7f7baba5.gz
This commit is contained in:
parent
697d524687
commit
e356bdaa8e
4 changed files with 134 additions and 22 deletions
31
builtin.c
31
builtin.c
|
@ -2519,6 +2519,37 @@ static int builtin_end( wchar_t **argv )
|
||||||
variables in the current loop scope won't die between laps.
|
variables in the current loop scope won't die between laps.
|
||||||
*/
|
*/
|
||||||
int kill_block = 1;
|
int kill_block = 1;
|
||||||
|
wchar_t *type = argv[1];
|
||||||
|
if( type )
|
||||||
|
{
|
||||||
|
int t = parser_get_block_type( type );
|
||||||
|
if( t != current_block->type )
|
||||||
|
{
|
||||||
|
if( t == -1 )
|
||||||
|
{
|
||||||
|
sb_printf( sb_err,
|
||||||
|
BUILTIN_END_BLOCK_UNKNOWN,
|
||||||
|
argv[0],
|
||||||
|
type,
|
||||||
|
parser_get_block_command( current_block->type ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb_printf( sb_err,
|
||||||
|
BUILTIN_END_BLOCK_MISMATCH,
|
||||||
|
argv[0],
|
||||||
|
type,
|
||||||
|
parser_get_block_command( current_block->type ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
builtin_print_help( argv[0], sb_err );
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
switch( current_block->type )
|
switch( current_block->type )
|
||||||
{
|
{
|
||||||
|
|
10
builtin.h
10
builtin.h
|
@ -67,6 +67,16 @@ enum
|
||||||
*/
|
*/
|
||||||
#define BUILTIN_ERR_TOO_MANY_ARGUMENTS _( L"%ls: Too many arguments\n" )
|
#define BUILTIN_ERR_TOO_MANY_ARGUMENTS _( L"%ls: Too many arguments\n" )
|
||||||
|
|
||||||
|
/**
|
||||||
|
Error message when block types mismatch in the end builtin, e.g. 'begin; end for'
|
||||||
|
*/
|
||||||
|
#define BUILTIN_END_BLOCK_MISMATCH _( L"%ls: Block mismatch: '%ls' vs. '%ls'\n" )
|
||||||
|
|
||||||
|
/**
|
||||||
|
Error message for unknown block type in the end builtin, e.g. 'begin; end beggin'
|
||||||
|
*/
|
||||||
|
#define BUILTIN_END_BLOCK_UNKNOWN _( L"%ls: Unknown block type '%ls'\n" )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Stringbuffer used to represent standard output
|
Stringbuffer used to represent standard output
|
||||||
*/
|
*/
|
||||||
|
|
74
parser.c
74
parser.c
|
@ -2259,12 +2259,18 @@ static int parse_job( process_t *p,
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !make_sub_block )
|
if( !make_sub_block )
|
||||||
|
{
|
||||||
|
int done=0;
|
||||||
|
|
||||||
|
for( tok_init( &subtok, end, 0 );
|
||||||
|
!done && tok_has_next( &subtok );
|
||||||
|
tok_next( &subtok ) )
|
||||||
{
|
{
|
||||||
|
|
||||||
tok_init( &subtok, end, 0 );
|
|
||||||
switch( tok_last_type( &subtok ) )
|
switch( tok_last_type( &subtok ) )
|
||||||
{
|
{
|
||||||
case TOK_END:
|
case TOK_END:
|
||||||
|
done = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TOK_REDIRECT_OUT:
|
case TOK_REDIRECT_OUT:
|
||||||
|
@ -2273,17 +2279,26 @@ static int parse_job( process_t *p,
|
||||||
case TOK_REDIRECT_FD:
|
case TOK_REDIRECT_FD:
|
||||||
case TOK_PIPE:
|
case TOK_PIPE:
|
||||||
{
|
{
|
||||||
|
done = 1;
|
||||||
make_sub_block = 1;
|
make_sub_block = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TOK_STRING:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
done = 1;
|
||||||
error( SYNTAX_ERROR,
|
error( SYNTAX_ERROR,
|
||||||
current_tokenizer_pos,
|
current_tokenizer_pos,
|
||||||
BLOCK_END_ERR_MSG );
|
BLOCK_END_ERR_MSG );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tok_destroy( &subtok );
|
tok_destroy( &subtok );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2733,7 +2748,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
||||||
/**
|
/**
|
||||||
\return the block type created by the specified builtin, or -1 on error.
|
\return the block type created by the specified builtin, or -1 on error.
|
||||||
*/
|
*/
|
||||||
static int parser_get_block_type( const wchar_t *cmd )
|
int parser_get_block_type( const wchar_t *cmd )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -2750,7 +2765,7 @@ static int parser_get_block_type( const wchar_t *cmd )
|
||||||
/**
|
/**
|
||||||
\return the block command that createa the specified block type, or null on error.
|
\return the block command that createa the specified block type, or null on error.
|
||||||
*/
|
*/
|
||||||
static const wchar_t *parser_get_block_command( int type )
|
const wchar_t *parser_get_block_command( int type )
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -3302,6 +3317,59 @@ int parser_test( const wchar_t * buff,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Try to make sure that arguments passed to 'end' is always the type of block to close
|
||||||
|
*/
|
||||||
|
if( wcscmp( cmd, L"end" ) == 0 )
|
||||||
|
{
|
||||||
|
if( (arg_count == 1) /*&& (count > 0)*/ )
|
||||||
|
{
|
||||||
|
|
||||||
|
int t = parser_get_block_type( tok_last( &tok ) );
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is ugly. We peek at the element
|
||||||
|
past the current element on the
|
||||||
|
block_type stack. It will always contain
|
||||||
|
the type of the block that just went out
|
||||||
|
of scope, which is what we need, but it
|
||||||
|
is not nice coding practice to search
|
||||||
|
through the 'junk pile' like that...
|
||||||
|
*/
|
||||||
|
if( t != block_type[count] )
|
||||||
|
{
|
||||||
|
err=1;
|
||||||
|
if( out )
|
||||||
|
{
|
||||||
|
if( t == -1 )
|
||||||
|
{
|
||||||
|
error( SYNTAX_ERROR,
|
||||||
|
tok_get_pos( &tok ),
|
||||||
|
BUILTIN_END_BLOCK_UNKNOWN,
|
||||||
|
L"end",
|
||||||
|
tok_last( &tok ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error( SYNTAX_ERROR,
|
||||||
|
tok_get_pos( &tok ),
|
||||||
|
BUILTIN_END_BLOCK_MISMATCH,
|
||||||
|
L"end",
|
||||||
|
tok_last( &tok ),
|
||||||
|
parser_get_block_command( block_type[count-1] ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
print_errors( out, prefix );
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
3
parser.h
3
parser.h
|
@ -377,5 +377,8 @@ const wchar_t *parser_current_filename();
|
||||||
*/
|
*/
|
||||||
void parser_stack_trace( block_t *b, string_buffer_t *buff);
|
void parser_stack_trace( block_t *b, string_buffer_t *buff);
|
||||||
|
|
||||||
|
int parser_get_block_type( const wchar_t *cmd );
|
||||||
|
const wchar_t *parser_get_block_command( int type );
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue