Improved error messages

darcs-hash:20051207160647-ac50b-4061540829a108381c20a1a6f3c8fd2d004a9800.gz
This commit is contained in:
axel 2005-12-08 02:06:47 +10:00
parent 0c877183b9
commit 4ba2709452
7 changed files with 216 additions and 150 deletions

View File

@ -1322,6 +1322,31 @@ static int builtin_read( wchar_t **argv )
return 1;
}
/*
Verify all variable names
*/
for( i=woptind; i<argc; i++ )
{
wchar_t *src;
if( !wcslen( argv[i] ) )
{
sb_printf( sb_err, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
return 1;
}
for( src=argv[i]; *src; src++ )
{
if( (!iswalnum(*src)) && (*src != L'_' ) )
{
sb_printf( sb_err, BUILTIN_ERR_VARCHAR, argv[0], *src );
sb_append2(sb_err, parser_current_line(), L"\n", (void *)0 );
return 1;
}
}
}
/*
The call to reader_readline may change woptind, so we save it away here
*/

View File

@ -42,6 +42,10 @@ enum
*/
#define BUILTIN_ERR_UNKNOWN L": Unknown option"
#define BUILTIN_ERR_VARCHAR L"%ls: Invalid character in variable name: '%lc'. Only alphanumerical characters and underscores are valid in a variable name.\n"
#define BUILTIN_ERR_VARNAME_ZERO L"%ls: Variable name can not be the empty string\n"
/**
Stringbuffer used to represent standard output
*/

View File

@ -40,10 +40,8 @@ static int parse_fill_name( string_buffer_t *name,
if (*src != L'[' && *src != L'\0')
{
sb_append(sb_err, L"set: Invalid character in variable name: ");
sb_append_char(sb_err, *src);
sb_append2(sb_err, L"\n", parser_current_line(), L"\n", (void *)0 );
sb_printf( sb_err, BUILTIN_ERR_VARCHAR, L"set", *src );
sb_append2(sb_err, parser_current_line(), L"\n", (void *)0 );
// builtin_print_help( L"set", sb_err );
return -1;
@ -439,7 +437,7 @@ int builtin_set( wchar_t **argv )
if( !wcslen( dest ) )
{
free( dest );
sb_printf( sb_err, L"%ls: Variable name must not be zero\n", argv[0] );
sb_printf( sb_err, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
return 1;
}
}

View File

@ -737,15 +737,14 @@ static int expand_variables( wchar_t *in, array_list_t *out )
{
error( SYNTAX_ERROR,
COMPLETE_VAR_DESC
COMPLETE_VAR2_DESC ,
-1 );
-1, COMPLETE_VAR_DESC
COMPLETE_VAR2_DESC );
}
else
{
error( SYNTAX_ERROR,
COMPLETE_VAR_DESC,
-1 );
-1,
COMPLETE_VAR_DESC);
}
is_ok = 0;
@ -795,8 +794,9 @@ static int expand_variables( wchar_t *in, array_list_t *out )
if( ( errno ) || ( end == &in[stop_pos] ) )
{
error( SYNTAX_ERROR,
L"Expected integer or \']\'",
-1 );
-1,
L"Expected integer or \']\'" );
is_ok = 0;
break;
}
@ -816,7 +816,9 @@ static int expand_variables( wchar_t *in, array_list_t *out )
int tmp = (int)al_get( &idx, j );
if( tmp < 1 || tmp > al_get_count( &l ) )
{
error( SYNTAX_ERROR, L"Array index out of bounds", -1 );
error( SYNTAX_ERROR,
-1,
L"Array index out of bounds" );
is_ok=0;
al_truncate( &idx, j );
break;
@ -877,8 +879,7 @@ static int expand_variables( wchar_t *in, array_list_t *out )
if( !(new_in = malloc( sizeof(wchar_t)*new_len )))
{
error( OOM, L"Out of memory", -1 );
is_ok = 0;
die_mem();
}
else
{
@ -1047,7 +1048,9 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
if( syntax_error )
{
error( SYNTAX_ERROR, L"Mismatched brackets", -1 );
error( SYNTAX_ERROR,
-1,
L"Mismatched brackets" );
return 0;
}
@ -1193,7 +1196,9 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
0 ) )
{
case -1:
error( SYNTAX_ERROR, L"Mismatched parans", -1 );
error( SYNTAX_ERROR,
-1,
L"Mismatched parans" );
return 0;
case 0:
al_push( out, in );
@ -1272,7 +1277,7 @@ wchar_t *expand_unescape( const wchar_t * in, int escape_special )
{
wchar_t *res = unescape( in, escape_special );
if( !res )
error( SYNTAX_ERROR, L"Unexpected end of string", -1 );
error( SYNTAX_ERROR, -1, L"Unexpected end of string" );
return res;
}
@ -1441,7 +1446,7 @@ int expand_string( wchar_t *str,
if( (pos == str) || ( *(pos-1) != L'\\' ) )
{
error( SUBSHELL_ERROR, L"Subshells not allowed", -1 );
error( SUBSHELL_ERROR, -1, L"Subshells not allowed" );
free( str );
al_destroy( &list1 );
al_destroy( &list2 );

277
parser.c
View File

@ -66,7 +66,7 @@ The fish parser. Contains functions for parsing code.
Error message for tokenizer error. The tokenizer message is
appended to this message.
*/
#define TOK_ERR_MSG L"Tokenizer error"
#define TOK_ERR_MSG L"Tokenizer error: %ls"
/**
Error message for short circut command error.
@ -101,7 +101,12 @@ The fish parser. Contains functions for parsing code.
/**
Error message for wildcards with no matches
*/
#define WILDCARD_ERR_MSG L"Warning: No match for wildcard "
#define WILDCARD_ERR_MSG L"Warning: No match for wildcard %ls"
/**
Error message for Posix-style assignment
*/
#define COMMAND_ASSIGN_ERR_MSG L"Unknown command %ls. Did you mean 'set VARIABLE VALUE'? For information on setting variable values, see the manual section on the set command by typing 'help set'."
/** Last error code */
int error_code;
@ -564,21 +569,17 @@ void parser_allow_function()
free( (void *) al_pop( &forbidden_function ) );
}
void error( int ec, const wchar_t *str, int p )
void error( int ec, int p, const wchar_t *str, ... )
{
error_code = ec;
wcsncpy( err_str, str, 256 );
err_pos = p;
}
va_list va;
error_code = ec;
err_pos = p;
va_start( va, str );
vswprintf( err_str, 256, str, va );
va_end( va );
/**
Wrapper for the error function, which sets the error string to "ec 'ea'".
*/
static void error_arg( int ec, const wchar_t *es, const wchar_t *ea, int p )
{
wchar_t *msg = wcsdupcat2( es, L" \'", ea, L"\'", 0 );
error( ec, msg, p );
free(msg);
}
wchar_t *get_filename( const wchar_t *cmd )
@ -824,20 +825,21 @@ int eval_args( const wchar_t *line, array_list_t *args )
case TOK_ERROR:
{
error_arg( SYNTAX_ERROR,
TOK_ERR_MSG,
tok_last(&tok),
tok_get_pos( &tok ) );
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
TOK_ERR_MSG,
tok_last(&tok) );
do_loop=0;
break;
}
default:
error_arg( SYNTAX_ERROR,
L"Unexpected token of type",
tok_get_desc( tok_last_type(&tok)),
tok_get_pos( &tok ) );
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
L"Unexpected token of type %ls",
tok_get_desc( tok_last_type(&tok)) );
do_loop=0;
break;
@ -1000,8 +1002,8 @@ static void parse_job_main_loop( process_t *p,
if( (p->type == INTERNAL_EXEC) )
{
error( SYNTAX_ERROR,
EXEC_ERR_MSG,
tok_get_pos( tok ) );
tok_get_pos( tok ),
EXEC_ERR_MSG );
return;
}
p->pipe_fd = wcstol( tok_last( tok ), 0, 10 );
@ -1079,10 +1081,11 @@ static void parse_job_main_loop( process_t *p,
err_pos=tok_get_pos( tok );
if( error_code == 0 )
{
error_arg( SYNTAX_ERROR,
L"Could not expand string",
tok_last(tok),
tok_get_pos( tok ) );
error( SYNTAX_ERROR,
tok_get_pos( tok ),
L"Could not expand string",
tok_last(tok) );
}
break;
}
@ -1155,27 +1158,27 @@ static void parse_job_main_loop( process_t *p,
target = expand_one( wcsdup( tok_last( tok ) ), 0);
if( target == 0 && error_code == 0 )
{
error_arg( SYNTAX_ERROR,
L"Could not expand string",
tok_last( tok ),
tok_get_pos( tok ) );
error( SYNTAX_ERROR,
tok_get_pos( tok ),
L"Could not expand string %ls",
tok_last( tok ) );
}
}
break;
default:
error_arg( SYNTAX_ERROR,
L"Expected redirection, got token of type",
tok_get_desc( tok_last_type(tok)),
tok_get_pos( tok ) );
error( SYNTAX_ERROR,
tok_get_pos( tok ),
L"Expected redirection, got token of type %ls",
tok_get_desc( tok_last_type(tok)) );
}
if( target == 0 || wcslen( target )==0 )
{
if( error_code == 0 )
error( SYNTAX_ERROR,
L"Invalid IO redirection",
tok_get_pos( tok ) );
tok_get_pos( tok ),
L"Invalid IO redirection" );
tok_next(tok);
}
else
@ -1216,11 +1219,12 @@ static void parse_job_main_loop( process_t *p,
if( ( new_io->param1.old_fd < 0 ) ||
( new_io->param1.old_fd > 10 ) )
{
error_arg( SYNTAX_ERROR,
L"Requested redirection to something "
L"that is not a file descriptor",
target,
tok_get_pos( tok ) );
error( SYNTAX_ERROR,
tok_get_pos( tok ),
L"Requested redirection to something "
L"that is not a file descriptor %ls",
target );
tok_next(tok);
}
free(target);
@ -1236,19 +1240,20 @@ static void parse_job_main_loop( process_t *p,
case TOK_ERROR:
{
error_arg( SYNTAX_ERROR,
TOK_ERR_MSG,
tok_last(tok),
tok_get_pos( tok ) );
error( SYNTAX_ERROR,
tok_get_pos( tok ),
TOK_ERR_MSG,
tok_last(tok) );
return;
}
default:
error_arg( SYNTAX_ERROR,
L"Unexpected token of type",
tok_get_desc( tok_last_type(tok)),
tok_get_pos( tok ) );
error( SYNTAX_ERROR,
tok_get_pos( tok ),
L"Unexpected token of type %ls",
tok_get_desc( tok_last_type(tok)) );
tok_next(tok);
break;
}
@ -1263,10 +1268,11 @@ static void parse_job_main_loop( process_t *p,
{
if( unmatched_wildcard && !matched_wildcard )
{
error_arg( WILDCARD_ERROR,
WILDCARD_ERR_MSG,
unmatched,
unmatched_pos );
error( WILDCARD_ERROR,
unmatched_pos,
WILDCARD_ERR_MSG,
unmatched );
}
}
free( unmatched );
@ -1311,10 +1317,11 @@ static int parse_job( process_t *p,
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES);
if( nxt == 0 )
{
error_arg( SYNTAX_ERROR,
L"Illegal command name ",
tok_last( tok ),
tok_get_pos( tok ) );
error( SYNTAX_ERROR,
tok_get_pos( tok ),
L"Illegal command name %ls",
tok_last( tok ) );
al_destroy( &args );
return 0;
}
@ -1323,10 +1330,10 @@ static int parse_job( process_t *p,
case TOK_ERROR:
{
error_arg( SYNTAX_ERROR,
TOK_ERR_MSG,
tok_last(tok),
tok_get_pos( tok ) );
error( SYNTAX_ERROR,
tok_get_pos( tok ),
TOK_ERR_MSG,
tok_last(tok) );
al_destroy( &args );
return 0;
@ -1334,10 +1341,11 @@ static int parse_job( process_t *p,
default:
{
error_arg( SYNTAX_ERROR,
L"Expected a command name, got token of type ",
tok_get_desc( tok_last_type(tok)),
tok_get_pos( tok ) );
error( SYNTAX_ERROR,
tok_get_pos( tok ),
L"Expected a command name, got token of type %ls",
tok_get_desc( tok_last_type(tok) ) );
al_destroy( &args );
return 0;
}
@ -1421,8 +1429,8 @@ static int parse_job( process_t *p,
if( p != j->first_process )
{
error( SYNTAX_ERROR,
EXEC_ERR_MSG,
tok_get_pos( tok ) );
tok_get_pos( tok ),
EXEC_ERR_MSG );
al_destroy( &args );
free(nxt);
return 0;
@ -1506,8 +1514,8 @@ static int parse_job( process_t *p,
if( al_get_count( &forbidden_function ) > MAX_RECURSION_DEPTH )
{
error( SYNTAX_ERROR,
RECURSION_ERR_MSG,
tok_get_pos( tok ) );
tok_get_pos( tok ),
RECURSION_ERR_MSG );
}
else
{
@ -1577,10 +1585,23 @@ static int parse_job( process_t *p,
}
else
{
error_arg( EVAL_ERROR,
L"Unknown command",
(wchar_t *)al_get( &args, 0 ),
tok_get_pos( tok ) );
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 ) );
}
else
{
error( EVAL_ERROR,
tok_get_pos( tok ),
L"Unknown command %ls",
(wchar_t *)al_get( &args, 0 ) );
}
}
}
}
@ -1597,8 +1618,8 @@ static int parse_job( process_t *p,
if( !end )
{
error( SYNTAX_ERROR,
L"Could not find end of block" ,
tok_get_pos( tok ) );
tok_get_pos( tok ),
L"Could not find end of block" );
}
if( !make_sub_block )
@ -1622,8 +1643,8 @@ static int parse_job( process_t *p,
default:
{
error( SYNTAX_ERROR,
BLOCK_END_ERR_MSG,
current_tokenizer_pos );
current_tokenizer_pos,
BLOCK_END_ERR_MSG );
}
}
tok_destroy( &subtok );
@ -1902,20 +1923,20 @@ static void eval_job( tokenizer *tok )
case TOK_ERROR:
{
error_arg( SYNTAX_ERROR,
TOK_ERR_MSG,
tok_last(tok),
tok_get_pos( tok ) );
error( SYNTAX_ERROR,
tok_get_pos( tok ),
TOK_ERR_MSG,
tok_last(tok) );
return;
}
default:
{
error_arg( SYNTAX_ERROR,
L"Expected a command string, got token of type",
tok_get_desc( tok_last_type(tok)),
tok_get_pos( tok ) );
error( SYNTAX_ERROR,
tok_get_pos( tok ),
L"Expected a command string, got token of type %ls",
tok_get_desc( tok_last_type(tok)) );
return;
}
@ -2098,8 +2119,9 @@ int parser_test( wchar_t * buff,
if( babble )
{
error( SYNTAX_ERROR,
COND_ERR_MSG,
tok_get_pos( &tok ) );
tok_get_pos( &tok ),
COND_ERR_MSG );
print_errors();
}
}
@ -2124,7 +2146,10 @@ int parser_test( wchar_t * buff,
{
if( count >= BLOCK_MAX_COUNT )
{
error( SYNTAX_ERROR, BLOCK_ERR_MSG, tok_get_pos( &tok ) );
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
BLOCK_ERR_MSG );
print_errors();
}
else
@ -2180,8 +2205,9 @@ int parser_test( wchar_t * buff,
if( babble )
{
error( SYNTAX_ERROR,
EXEC_ERR_MSG,
tok_get_pos( &tok ) );
tok_get_pos( &tok ),
EXEC_ERR_MSG );
print_errors();
}
@ -2202,8 +2228,9 @@ int parser_test( wchar_t * buff,
if( babble )
{
error( SYNTAX_ERROR,
EXEC_ERR_MSG,
tok_get_pos( &tok ) );
tok_get_pos( &tok ),
EXEC_ERR_MSG );
print_errors();
}
@ -2226,8 +2253,9 @@ int parser_test( wchar_t * buff,
if( babble )
{
error( SYNTAX_ERROR,
L"'case' builtin not inside of switch block",
tok_get_pos( &tok ) );
tok_get_pos( &tok ),
L"'case' builtin not inside of switch block" );
print_errors();
}
}
@ -2258,9 +2286,9 @@ int parser_test( wchar_t * buff,
if( babble )
{
error( SYNTAX_ERROR,
L"Loop control command while not inside of loop",
tok_get_pos( &tok ) );
print_errors();
tok_get_pos( &tok ),
L"Loop control command while not inside of loop" );
print_errors();
}
}
}
@ -2276,9 +2304,9 @@ int parser_test( wchar_t * buff,
if( babble )
{
error( SYNTAX_ERROR,
L"'else' builtin not inside of if block",
tok_get_pos( &tok ) );
print_errors();
tok_get_pos( &tok ),
L"'else' builtin not inside of if block" );
print_errors();
}
}
@ -2293,8 +2321,8 @@ int parser_test( wchar_t * buff,
if( babble )
{
error( SYNTAX_ERROR,
L"'end' command outside of block",
tok_get_pos( &tok ) );
tok_get_pos( &tok ),
L"'end' command outside of block" );
print_errors();
}
}
@ -2313,8 +2341,8 @@ int parser_test( wchar_t * buff,
if( babble )
{
error( SYNTAX_ERROR,
L"Redirection error",
tok_get_pos( &tok ) );
tok_get_pos( &tok ),
L"Redirection error" );
print_errors();
}
}
@ -2329,9 +2357,9 @@ int parser_test( wchar_t * buff,
if( babble )
{
error( SYNTAX_ERROR,
CMD_ERR_MSG,
tok_get_pos( &tok ) );
print_errors();
tok_get_pos( &tok ),
CMD_ERR_MSG );
print_errors();
}
}
needs_cmd=0;
@ -2349,8 +2377,9 @@ int parser_test( wchar_t * buff,
if( babble )
{
error( SYNTAX_ERROR,
EXEC_ERR_MSG,
tok_get_pos( &tok ) );
tok_get_pos( &tok ),
EXEC_ERR_MSG );
print_errors();
}
}
@ -2367,8 +2396,9 @@ int parser_test( wchar_t * buff,
if( babble )
{
error( SYNTAX_ERROR,
CMD_ERR_MSG,
tok_get_pos( &tok ) );
tok_get_pos( &tok ),
CMD_ERR_MSG );
print_errors();
}
}
@ -2385,10 +2415,12 @@ int parser_test( wchar_t * buff,
err = 1;
if( babble )
{
error_arg( SYNTAX_ERROR,
TOK_ERR_MSG,
tok_last(&tok),
tok_get_pos( &tok ) );
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
TOK_ERR_MSG,
tok_last(&tok) );
print_errors();
//debug( 2, tok_last( &tok) );
}
@ -2402,8 +2434,9 @@ int parser_test( wchar_t * buff,
if( babble )
{
error( SYNTAX_ERROR,
COND_ERR_MSG,
tok_get_pos( &tok ) );
tok_get_pos( &tok ),
COND_ERR_MSG );
print_errors();
}
}
@ -2412,8 +2445,8 @@ int parser_test( wchar_t * buff,
if( babble && count>0 )
{
error( SYNTAX_ERROR,
END_ERR_MSG L"\n",
block_pos[count-1] );
block_pos[count-1],
END_ERR_MSG );
print_errors();
}

View File

@ -200,10 +200,11 @@ int eval_args( const wchar_t *line,
Sets the current error
\param ec The new error code
\param str The new error message
\param p The character offset at which the error occured
\param str The printf-style error message filter
*/
void error( int ec, const wchar_t *str, int p );
void error( int ec, int p, const wchar_t *str, ... );
/**
Tests if the specified commands parameters should be interpreted as another command, which will be true if the command is either 'command', 'exec', 'if', 'while' or 'builtin'.

View File

@ -358,7 +358,7 @@ int wildcard_expand( const wchar_t *wc,
/* Description for completions */
string_buffer_t sb_desc;
// debug( 3, L"WILDCARD_EXPAND %ls in %ls", wc, base_dir );
// debug( 3, L"WILDCARD_EXPAND %ls in %ls", wc, base_dir );
if( flags & ACCEPT_INCOMPLETE )
{