Make sure code validation error output for e.g. the complete builtin can be redirected, and that it has the prefix 'complete', not 'fish'

darcs-hash:20060602021517-ac50b-5e566aefbd1c9bcb3a5f11f9fc1125d8c1d9e936.gz
This commit is contained in:
axel 2006-06-02 12:15:17 +10:00
parent 67f216fa55
commit a1a2773cbf
5 changed files with 112 additions and 82 deletions

View file

@ -2502,7 +2502,7 @@ static int builtin_end( wchar_t **argv )
//fwprintf( stderr, L"Function: %ls\n", def );
if( !is_interactive || !parser_test( def, 1 ) )
if( !is_interactive || !parser_test( def, sb_err, argv[0] ) )
{
function_add( current_block->param1.function_name,
def,

View file

@ -30,7 +30,10 @@ const static wchar_t *temporary_buffer;
/*
builtin_complete_* are a set of rather silly looping functions that
make sure that all the proper combinations of complete_add or
complete_remove get called.
complete_remove get called. This is needed since complete allows you
to specify multiple switches on a single commandline, like 'complete
-s a -s b -s c', but the complete_add function only accepts one
short switch and one long switch.
*/
static void builtin_complete_add2( const wchar_t *cmd,
@ -455,14 +458,14 @@ int builtin_complete( wchar_t **argv )
{
if( condition && wcslen( condition ) )
{
if( parser_test( condition, 0 ) )
if( parser_test( condition, 0, 0 ) )
{
sb_printf( sb_err,
L"%ls: Condition '%ls' contained a syntax error\n",
argv[0],
condition );
parser_test( condition, 1 );
parser_test( condition, sb_err, argv[0] );
res = 1;
}
@ -473,14 +476,14 @@ int builtin_complete( wchar_t **argv )
{
if( comp && wcslen( comp ) )
{
if( parser_test_args( comp, 0 ) )
if( parser_test_args( comp, 0, 0 ) )
{
sb_printf( sb_err,
L"%ls: Completion '%ls' contained a syntax error\n",
argv[0],
comp );
parser_test_args( comp, 1 );
parser_test_args( comp, sb_err, argv[0] );
res = 1;
}

139
parser.c
View file

@ -919,23 +919,40 @@ void parser_destroy()
/**
Print error message if an error has occured while parsing
*/
static void print_errors()
static void print_errors( string_buffer_t *target, const wchar_t *prefix )
{
if( error_code )
{
int tmp;
debug( 0, L"%ls", err_str );
sb_printf( target, L"%ls: %ls\n", prefix, err_str );
tmp = current_tokenizer_pos;
current_tokenizer_pos = err_pos;
fwprintf( stderr, L"%ls", parser_current_line() );
sb_printf( target, L"%ls", parser_current_line() );
current_tokenizer_pos=tmp;
}
}
static void print_errors_stderr()
{
if( error_code )
{
debug( 0, L"%ls", err_str );
int tmp;
tmp = current_tokenizer_pos;
current_tokenizer_pos = err_pos;
fwprintf( stderr, L"%ls", parser_current_line() );
current_tokenizer_pos=tmp;
}
}
int eval_args( const wchar_t *line, array_list_t *args )
{
tokenizer tok;
@ -1004,8 +1021,9 @@ int eval_args( const wchar_t *line, array_list_t *args )
}
}
}
print_errors_stderr();
print_errors();
tok_destroy( &tok );
current_tokenizer=previous_tokenizer;
@ -2516,7 +2534,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
parser_pop_block();
}
print_errors();
print_errors_stderr();
tok_destroy( current_tokenizer );
free( current_tokenizer );
@ -2565,7 +2583,7 @@ static int parser_get_block_type( const wchar_t *cmd )
}
static int parser_test_argument( const wchar_t *arg, int babble, int offset )
static int parser_test_argument( const wchar_t *arg, string_buffer_t *out, const wchar_t *prefix, int offset )
{
wchar_t *unesc;
wchar_t *pos;
@ -2584,12 +2602,12 @@ static int parser_test_argument( const wchar_t *arg, int babble, int offset )
{
case -1:
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
offset,
L"Mismatched parans" );
print_errors();
print_errors( out, prefix);
}
free( arg_cpy );
return 1;
@ -2611,7 +2629,7 @@ static int parser_test_argument( const wchar_t *arg, int babble, int offset )
// debug( 1, L"%ls -> %ls %ls", arg_cpy, subst, tmp.buff );
err |= parser_test( subst, babble );
err |= parser_test( subst, out, prefix );
free( subst );
free( arg_cpy );
@ -2645,13 +2663,13 @@ static int parser_test_argument( const wchar_t *arg, int babble, int offset )
case BRACKET_BEGIN:
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
offset,
COMPLETE_VAR_BRACKET_DESC );
print_errors();
print_errors( out, prefix);
}
break;
}
@ -2659,12 +2677,12 @@ static int parser_test_argument( const wchar_t *arg, int babble, int offset )
case INTERNAL_SEPARATOR:
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
offset,
COMPLETE_VAR_PARAN_DESC );
print_errors();
print_errors( out, prefix);
}
break;
}
@ -2672,12 +2690,12 @@ static int parser_test_argument( const wchar_t *arg, int babble, int offset )
case 0:
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
offset,
COMPLETE_VAR_NULL_DESC );
print_errors();
print_errors( out, prefix);
}
break;
}
@ -2691,13 +2709,13 @@ static int parser_test_argument( const wchar_t *arg, int babble, int offset )
!wcsvarchr(n) )
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
offset,
COMPLETE_VAR_DESC,
*(pos+1) );
print_errors();
print_errors( out, prefix);
}
}
@ -2719,7 +2737,7 @@ static int parser_test_argument( const wchar_t *arg, int babble, int offset )
}
int parser_test_args(const wchar_t * buff,
int babble )
string_buffer_t *out, const wchar_t *prefix )
{
tokenizer tok;
tokenizer *previous_tokenizer = current_tokenizer;
@ -2739,7 +2757,7 @@ int parser_test_args(const wchar_t * buff,
case TOK_STRING:
{
err |= parser_test_argument( tok_last( &tok ), babble, tok_get_pos( &tok ) );
err |= parser_test_argument( tok_last( &tok ), out, prefix, tok_get_pos( &tok ) );
break;
}
@ -2750,13 +2768,13 @@ int parser_test_args(const wchar_t * buff,
case TOK_ERROR:
{
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
TOK_ERR_MSG,
tok_last(&tok) );
print_errors();
print_errors( out, prefix );
}
err=1;
do_loop=0;
@ -2765,13 +2783,13 @@ int parser_test_args(const wchar_t * buff,
default:
{
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
UNEXPECTED_TOKEN_ERR_MSG,
tok_get_desc( tok_last_type(&tok)) );
print_errors();
print_errors( out, prefix );
}
err=1;
do_loop=0;
@ -2791,7 +2809,8 @@ int parser_test_args(const wchar_t * buff,
}
int parser_test( const wchar_t * buff,
int babble )
string_buffer_t *out,
const wchar_t *prefix)
{
tokenizer tok;
/*
@ -2842,14 +2861,14 @@ int parser_test( const wchar_t * buff,
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES ) ) )
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
ILLEGAL_CMD_ERR_MSG,
cmd );
print_errors();
print_errors( out, prefix );
}
}
@ -2865,13 +2884,13 @@ int parser_test( const wchar_t * buff,
0 ) )
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
COND_ERR_MSG );
print_errors();
print_errors( out, prefix );
}
}
@ -2899,7 +2918,7 @@ int parser_test( const wchar_t * buff,
tok_get_pos( &tok ),
BLOCK_ERR_MSG );
print_errors();
print_errors( out, prefix );
}
else
{
@ -2934,13 +2953,13 @@ int parser_test( const wchar_t * buff,
if( is_pipeline )
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
EXEC_ERR_MSG );
print_errors();
print_errors( out, prefix );
}
}
@ -2956,13 +2975,13 @@ int parser_test( const wchar_t * buff,
if( is_pipeline )
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
EXEC_ERR_MSG );
print_errors();
print_errors( out, prefix );
}
}
@ -2978,13 +2997,13 @@ int parser_test( const wchar_t * buff,
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
INVALID_CASE_ERR_MSG );
print_errors();
print_errors( out, prefix);
}
}
}
@ -3010,12 +3029,12 @@ int parser_test( const wchar_t * buff,
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
INVALID_LOOP_ERR_MSG );
print_errors();
print_errors( out, prefix );
}
}
}
@ -3028,13 +3047,13 @@ int parser_test( const wchar_t * buff,
if( !count || block_type[count-1]!=IF )
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
INVALID_ELSE_ERR_MSG );
print_errors();
print_errors( out, prefix );
}
}
@ -3046,18 +3065,18 @@ int parser_test( const wchar_t * buff,
if( count < 0 )
{
err = 1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
INVALID_END_ERR_MSG );
print_errors();
print_errors( out, prefix );
}
}
}
else
{
err |= parser_test_argument( tok_last( &tok ), babble, tok_get_pos( &tok ) );
err |= parser_test_argument( tok_last( &tok ), out, prefix, tok_get_pos( &tok ) );
/*
If possible, keep track of number of supplied arguments
@ -3082,14 +3101,14 @@ int parser_test( const wchar_t * buff,
{
err = 1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
BUILTIN_FOR_ERR_IN,
L"for" );
print_errors();
print_errors( out, prefix );
}
}
}
@ -3107,12 +3126,12 @@ int parser_test( const wchar_t * buff,
if( !had_cmd )
{
err = 1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
INVALID_REDIRECTION_ERR_MSG );
print_errors();
print_errors( out, prefix );
}
}
break;
@ -3123,13 +3142,13 @@ int parser_test( const wchar_t * buff,
if( needs_cmd && !had_cmd )
{
err = 1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
CMD_ERR_MSG,
tok_get_desc( tok_last_type(&tok)));
print_errors();
print_errors( out, prefix );
}
}
needs_cmd=0;
@ -3144,7 +3163,7 @@ int parser_test( const wchar_t * buff,
if( !had_cmd )
{
err=1;
if( babble )
if( out )
{
if( tok_get_pos(&tok)>0 && buff[tok_get_pos(&tok)-1] == L'|' )
{
@ -3162,19 +3181,19 @@ int parser_test( const wchar_t * buff,
tok_get_desc( tok_last_type(&tok)));
}
print_errors();
print_errors( out, prefix );
}
}
else if( forbid_pipeline )
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
EXEC_ERR_MSG );
print_errors();
print_errors( out, prefix );
}
}
else
@ -3191,7 +3210,7 @@ int parser_test( const wchar_t * buff,
if( !had_cmd )
{
err = 1;
if( babble )
if( out )
{
if( tok_get_pos(&tok)>0 && buff[tok_get_pos(&tok)-1] == L'&' )
{
@ -3209,7 +3228,7 @@ int parser_test( const wchar_t * buff,
tok_get_desc( tok_last_type(&tok)));
}
print_errors();
print_errors( out, prefix );
}
}
@ -3223,7 +3242,7 @@ int parser_test( const wchar_t * buff,
case TOK_ERROR:
default:
err = 1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
@ -3231,7 +3250,7 @@ int parser_test( const wchar_t * buff,
tok_last(&tok) );
print_errors();
print_errors( out, prefix );
//debug( 2, tok_last( &tok) );
}
break;
@ -3241,23 +3260,23 @@ int parser_test( const wchar_t * buff,
if( needs_cmd )
{
err=1;
if( babble )
if( out )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
COND_ERR_MSG );
print_errors();
print_errors( out, prefix );
}
}
if( babble && count>0 )
if( out && count>0 )
{
error( SYNTAX_ERROR,
block_pos[count-1],
BLOCK_END_ERR_MSG );
print_errors();
print_errors( out, prefix );
}
tok_destroy( &tok );

View file

@ -320,7 +320,7 @@ const wchar_t *parser_get_block_desc( int block );
contains errors, and the second bit is set if the string contains
an unclosed block.
*/
int parser_test( const wchar_t * buff, int babble );
int parser_test( const wchar_t * buff, string_buffer_t *out, const wchar_t *prefix );
/**
Test if the specified string can be parsed as an argument list,
@ -328,7 +328,7 @@ int parser_test( const wchar_t * buff, int babble );
string contains errors, and the second bit is set if the string
contains an unclosed block.
*/
int parser_test_args( const wchar_t * buff, int babble );
int parser_test_args( const wchar_t * buff, string_buffer_t *out, const wchar_t *prefix );
/**
Returns the full path of the specified directory. If the \c in is a

View file

@ -2099,10 +2099,15 @@ void reader_run_command( wchar_t *cmd )
static int shell_test( wchar_t *b )
{
if( parser_test( b, 0 ) )
if( parser_test( b, 0, 0 ) )
{
string_buffer_t sb;
sb_init( &sb );
writech( L'\n' );
parser_test( b, 1 );
parser_test( b, &sb, L"fish" );
fwprintf( stderr, L"%ls", sb.buff );
sb_destroy( &sb );
return 1;
}
return 0;
@ -2944,18 +2949,21 @@ static int read_ni( int fd )
if( str )
{
if( !parser_test( str, 1 ) )
{
eval( str, 0, TOP );
}
else
{
/*
No error reporting - parser_test did that for us
*/
res = 1;
}
free( str );
string_buffer_t sb;
sb_init( &sb );
if( !parser_test( str, &sb, L"fish" ) )
{
eval( str, 0, TOP );
}
else
{
fwprintf( stderr, L"%ls", sb.buff );
res = 1;
}
sb_destroy( &sb );
free( str );
}
else
{