Use csh-style error rules with wildcards, i.e. if no matches are found, the command is not executed

darcs-hash:20051203164356-ac50b-1b1818db2698eab9ae765a5af1e259bce3ab37e7.gz
This commit is contained in:
axel 2005-12-04 02:43:56 +10:00
parent e2ebc0e443
commit 9b4c34aa4c
9 changed files with 218 additions and 75 deletions

View file

@ -1213,10 +1213,12 @@ static void complete_cmd( const wchar_t *cmd,
array_list_t tmp;
al_init( &tmp );
expand_string( wcsdup(cmd),
if( expand_string( wcsdup(cmd),
comp,
ACCEPT_INCOMPLETE | EXECUTABLES_ONLY );
ACCEPT_INCOMPLETE | EXECUTABLES_ONLY ) != EXPAND_ERROR )
{
complete_cmd_desc( cmd, comp );
}
al_destroy( &tmp );
}
else
@ -1237,15 +1239,16 @@ static void complete_cmd( const wchar_t *cmd,
al_init( &tmp );
expand_string( nxt_completion,
if( expand_string( nxt_completion,
&tmp,
ACCEPT_INCOMPLETE |
EXECUTABLES_ONLY );
EXECUTABLES_ONLY ) != EXPAND_ERROR )
{
for( i=0; i<al_get_count(&tmp); i++ )
{
al_push( comp, al_get( &tmp, i ) );
}
}
al_destroy( &tmp );
@ -1290,9 +1293,10 @@ static void complete_cmd( const wchar_t *cmd,
al_init( &tmp );
expand_string( nxt_completion,
if( expand_string( nxt_completion,
&tmp,
ACCEPT_INCOMPLETE | DIRECTORIES_ONLY );
ACCEPT_INCOMPLETE | DIRECTORIES_ONLY ) != EXPAND_ERROR )
{
for( i=0; i<al_get_count(&tmp); i++ )
{
@ -1310,6 +1314,7 @@ static void complete_cmd( const wchar_t *cmd,
free(nxt);
}
}
}
al_destroy( &tmp );

View file

@ -300,6 +300,12 @@ Example:
<code>???</code> matches any file in the current directory whose name is exactly three characters long.
If no matches are founf for a specific wildcard, it will expand intto
zero arguments, i.e. to nothing. If none of the wildcarded arguments
sent to a command result in any matches, the command will not be
executed. If this happens when using the shell interactively, a
warning will also be printed.
\subsection expand-command-substitution Command substitution
If a parameter contains a set of parenthesis, the text enclosed by the

2
exec.c
View file

@ -1201,7 +1201,7 @@ int exec_subshell( const wchar_t *cmd,
if( !cmd )
{
debug( 1,
L"Sent null command to subshell. This is a fish bug. If it can be reproduced, please send a bug report to %ls",
L"Sent null command to subshell. This is a fish bug. If it can be reproduced, please send a bug report to %s",
PACKAGE_BUGREPORT );
return 0;
}

View file

@ -1390,11 +1390,14 @@ int expand_string( wchar_t *str,
int i;
int subshell_ok = 1;
int res = EXPAND_OK;
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( str ) )
{
al_push( end_out, str );
return 1;
return EXPAND_OK;
}
al_init( &list1 );
@ -1416,7 +1419,7 @@ int expand_string( wchar_t *str,
free( str );
al_destroy( &list1 );
al_destroy( &list2 );
return 0;
return EXPAND_ERROR;
}
pos++;
}
@ -1430,7 +1433,7 @@ int expand_string( wchar_t *str,
if( !subshell_ok )
{
al_destroy( &list1 );
return 0;
return EXPAND_ERROR;
}
else
{
@ -1464,7 +1467,7 @@ int expand_string( wchar_t *str,
{
al_destroy( in );
al_destroy( out );
return 0;
return EXPAND_ERROR;
}
}
}
@ -1481,7 +1484,7 @@ int expand_string( wchar_t *str,
{
al_destroy( in );
al_destroy( out );
return 0;
return EXPAND_ERROR;
}
}
al_truncate( in, 0 );
@ -1496,17 +1499,22 @@ int expand_string( wchar_t *str,
{
al_destroy( in );
al_destroy( out );
return 0;
return EXPAND_ERROR;
}
if( flags & ACCEPT_INCOMPLETE )
{
if( *next == PROCESS_EXPAND )
{
/*
If process expantion matches, we are not
interested in other completions, so we
short-circut and return
*/
expand_pid( next, flags, end_out );
al_destroy( in );
al_destroy( out );
return 1;
return EXPAND_OK;
}
else
al_push( out, next );
@ -1517,7 +1525,7 @@ int expand_string( wchar_t *str,
{
al_destroy( in );
al_destroy( out );
return 0;
return EXPAND_ERROR;
}
}
}
@ -1550,19 +1558,20 @@ int expand_string( wchar_t *str,
case 0:
if( !(flags & ACCEPT_INCOMPLETE) )
{
break;
if( res == EXPAND_OK )
res = EXPAND_WILDCARD_NO_MATCH;
}
break;
case 1:
res = EXPAND_WILDCARD_MATCH;
sort_list( out );
al_push_all( end_out, out );
al_truncate( out, 0 );
break;
default:
fwprintf( stderr, L"error\n" );
/*al_destroy( &list1 );*/
/*al_destroy( &list2 );*/
/*return 0;*/
}
}
else
@ -1577,7 +1586,8 @@ int expand_string( wchar_t *str,
al_destroy( out );
}
return 1;
return res;
}

View file

@ -84,6 +84,23 @@ enum
}
;
/**
These are the possible return values for expand_string
*/
enum
{
/** Error */
EXPAND_ERROR,
/** Ok */
EXPAND_OK,
/** Ok, a wildcard in the string matched no files */
EXPAND_WILDCARD_NO_MATCH,
/* Ok, a wildcard in the string matched a file */
EXPAND_WILDCARD_MATCH
}
;
/** Character for separating two array elements. We use 30, i.e. the ascii record separator since that seems logical. */
#define ARRAY_SEP 0x1e
@ -111,6 +128,7 @@ enum
\param in The parameter to expand
\param flag Specifies if any expantion pass should be skipped. Legal values are any combination of EXPAND_SKIP_SUBSHELL EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
\param out The list to which the result will be appended.
\return One of EXPAND_OK, EXPAND_ERROR, EXPAND_WILDCARD_MATCH and EXPAND_WILDCARD_NO_MATCH
*/
int expand_string( wchar_t *in, array_list_t *out, int flag );

View file

@ -98,6 +98,11 @@ The fish parser. Contains functions for parsing code.
*/
#define CMD_ERR_MSG L"Expected command"
/**
Error message for wildcards with no matches
*/
#define WILDCARD_ERR_MSG L"Warning: No match for wildcard "
/** Last error code */
int error_code;
@ -152,23 +157,23 @@ static int parse_job( process_t *p,
typedef struct
{
/**
Time spent executing the specified command, including parse time for nested blocks
Time spent executing the specified command, including parse time for nested blocks.
*/
int exec;
/**
Time spent parsing the specified command, incvluding execution time for command substitutions
Time spent parsing the specified command, including execution time for command substitutions.
*/
int parse;
/**
The block level of the specified command
The block level of the specified command. nested blocks and command substitutions both increase the block level.
*/
int level;
/**
If the execution of this command was skipped
If the execution of this command was skipped.
*/
int skipped;
/**
The command string
The command string.
*/
wchar_t *cmd;
} profile_element_t;
@ -757,6 +762,12 @@ static void print_errors()
{
int tmp;
/*
Wildcard warnings are only printed in interactive mode
*/
if( ( error_code == WILDCARD_ERROR ) && !is_interactive )
return;
debug( 0, L"%ls", err_str );
@ -791,10 +802,20 @@ int eval_args( const wchar_t *line, array_list_t *args )
switch(tok_last_type( &tok ) )
{
case TOK_STRING:
if( !expand_string( wcsdup(tok_last( &tok )), args, 0 ) )
switch( expand_string( wcsdup(tok_last( &tok )), args, 0 ) )
{
case EXPAND_ERROR:
{
err_pos=tok_get_pos( &tok );
do_loop=0;
break;
}
default:
{
break;
}
}
break;
@ -948,6 +969,11 @@ static void parse_job_main_loop( process_t *p,
int proc_is_count=0;
int matched_wildcard = 0, unmatched_wildcard = 0;
wchar_t *unmatched = 0;
int unmatched_pos=0;
/*
Test if this is the 'count' command. We need to special case
count, since it should display a help message on 'count .h',
@ -1045,10 +1071,10 @@ static void parse_job_main_loop( process_t *p,
wcscpy( p->actual_cmd, L"count" );
}
if( !expand_string( wcsdup(tok_last( tok )),
args,
0 )
)
switch( expand_string( wcsdup(tok_last( tok )), args, 0 ) )
{
case EXPAND_ERROR:
{
err_pos=tok_get_pos( tok );
if( error_code == 0 )
@ -1058,7 +1084,34 @@ static void parse_job_main_loop( process_t *p,
tok_last(tok),
tok_get_pos( tok ) );
}
break;
}
case EXPAND_WILDCARD_NO_MATCH:
{
unmatched_wildcard = 1;
if( !unmatched )
{
unmatched = wcsdup(tok_last( tok ));
unmatched_pos = tok_get_pos( tok );
}
break;
}
case EXPAND_WILDCARD_MATCH:
{
matched_wildcard = 1;
break;
}
case EXPAND_OK:
{
break;
}
}
}
break;
@ -1205,6 +1258,19 @@ static void parse_job_main_loop( process_t *p,
tok_next( tok );
}
if( !error_code )
{
if( unmatched_wildcard && !matched_wildcard )
{
error_arg( WILDCARD_ERROR,
WILDCARD_ERR_MSG,
unmatched,
unmatched_pos );
}
}
free( unmatched );
return;
}
@ -1240,6 +1306,7 @@ static int parse_job( process_t *p,
switch( tok_last_type( tok ))
{
case TOK_STRING:
{
nxt = expand_one( wcsdup(tok_last( tok )),
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES);
if( nxt == 0 )
@ -1252,6 +1319,7 @@ static int parse_job( process_t *p,
return 0;
}
break;
}
case TOK_ERROR:
{
@ -1265,6 +1333,7 @@ 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)),
@ -1272,6 +1341,7 @@ static int parse_job( process_t *p,
al_destroy( &args );
return 0;
}
}
int mark = tok_get_pos( tok );
@ -1377,7 +1447,7 @@ static int parse_job( process_t *p,
int new_block = 0;
tok_next( tok );
if( (current_block->type != WHILE) )
if( ( current_block->type != WHILE ) )
{
new_block = 1;
}

View file

@ -125,12 +125,34 @@ enum while_status
*/
enum parser_error
{
/**
No error
*/
NO_ERR=0,
/**
An error in the syntax
*/
SYNTAX_ERROR,
/**
Error occured while evaluating commands
*/
EVAL_ERROR,
/**
Out of memory error
*/
OOM,
/**
Stack inconsistency error
*/
STACK_ERROR,
SUBSHELL_ERROR
/**
Error while evaluating subshell
*/
SUBSHELL_ERROR,
/**
No files matching wildcards where found
*/
WILDCARD_ERROR
}
;

View file

@ -7,12 +7,18 @@
internal commands use wide characters and hence this library is
useful.
If you want to use this version of getopt in your program, simply
copy wgetopt.c and wgetopt.h into your program, include wgetopt.h,
and use all the regular getopt functions, prefixing every
function, global variable and structure with a 'w', and use only
wide character strings. There are no other functional changes in
this version of getopt besides using wide character strings.
If you want to use this version of getopt in your program,
download the fish sourcecode, available at <a
href='http://roo.no-ip.org/fish/'>the fish homepage</a>. Extract
the sourcode, copy wgetopt.c and wgetopt.h into your program
directory, include wgetopt.h in your program, and use all the
regular getopt functions, prefixing every function, global
variable and structure with a 'w', and use only wide character
strings. There are no other functional changes in this version of
getopt besides using wide character strings.
For examples of how to use wgetopt, see the fish builtin
functions, many of which are defined in builtin.c.
*/

View file

@ -7,12 +7,18 @@
internal commands use wide characters and hence this library is
useful.
If you want to use this version of getopt in your program, simply
copy wgetopt.c and wgetopt.h into your program, include wgetopt.h,
and use all the regular getopt functions, prefixing every
function, global variable and structure with a 'w', and use only
wide character strings. There are no other functional changes in
this version of getopt besides using wide character strings.
If you want to use this version of getopt in your program,
download the fish sourcecode, available at <a
href='http://roo.no-ip.org/fish/'>the fish homepage</a>. Extract
the sourcode, copy wgetopt.c and wgetopt.h into your program
directory, include wgetopt.h in your program, and use all the
regular getopt functions, prefixing every function, global
variable and structure with a 'w', and use only wide character
strings. There are no other functional changes in this version of
getopt besides using wide character strings.
For examples of how to use wgetopt, see the fish builtin
functions, many of which are defined in builtin.c.
*/