mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 13:39:02 +00:00
Migrated off of old variant of expand_one that used halloc
This commit is contained in:
parent
409f70c7f3
commit
0b4b6c498d
4 changed files with 63 additions and 114 deletions
41
expand.cpp
41
expand.cpp
|
@ -1809,47 +1809,6 @@ int expand_string2( const wcstring &input, std::vector<completion_t> &output, in
|
|||
return res;
|
||||
}
|
||||
|
||||
wchar_t *expand_one( void *context, const wchar_t *string, int flags )
|
||||
{
|
||||
std::vector<completion_t> l;
|
||||
int res;
|
||||
wchar_t *one;
|
||||
|
||||
CHECK( string, 0 );
|
||||
|
||||
if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( string ) )
|
||||
{
|
||||
halloc_register( context, (void *)string );
|
||||
return (wchar_t *)string;
|
||||
}
|
||||
|
||||
// al_init( &l );
|
||||
res = expand_string2( string, l, flags );
|
||||
if( !res )
|
||||
{
|
||||
one = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( l.size() != 1 )
|
||||
{
|
||||
one=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
one = wcsdup( l.at(0).completion.c_str() );
|
||||
// al_set( &l, 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
// al_foreach( &l, &free );
|
||||
// al_destroy( &l );
|
||||
|
||||
if (context)
|
||||
halloc_register( context, one );
|
||||
return one;
|
||||
}
|
||||
|
||||
bool expand_one(wcstring &string, int flags) {
|
||||
std::vector<completion_t> completions;
|
||||
bool result = false;
|
||||
|
|
11
expand.h
11
expand.h
|
@ -157,17 +157,10 @@ __warn_unused int expand_string2( const wcstring &input, std::vector<completion_
|
|||
expands to more than one string. This is used for expanding command
|
||||
names.
|
||||
|
||||
If \c context is non-null, the returning string ill be registered
|
||||
to be free'd when context is free'd.
|
||||
|
||||
\param context the halloc context to use for automatic deallocation
|
||||
\param in The parameter to expand
|
||||
\param inout_str The parameter to expand in-place
|
||||
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_CMDSUBST EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
|
||||
\return The expanded parameter, or 0 on failiure
|
||||
\return Whether expansion succeded
|
||||
*/
|
||||
wchar_t *expand_one( void *context, const wchar_t *in, int flag );
|
||||
|
||||
/** expand_one for a wcstring. Modifies the string in-place, returning true on success and false on failure */
|
||||
bool expand_one( wcstring &inout_str, int flag );
|
||||
|
||||
/**
|
||||
|
|
|
@ -772,7 +772,8 @@ void tokenize( const wchar_t * const buff, int * const color, const int pos, arr
|
|||
break;
|
||||
}
|
||||
|
||||
wchar_t *target=0;
|
||||
wcstring target_str;
|
||||
const wchar_t *target=NULL;
|
||||
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_REDIRECTION;
|
||||
tok_next( &tok );
|
||||
|
@ -785,7 +786,10 @@ void tokenize( const wchar_t * const buff, int * const color, const int pos, arr
|
|||
{
|
||||
case TOK_STRING:
|
||||
{
|
||||
target = expand_one( context, wcsdup( tok_last( &tok ) ), EXPAND_SKIP_CMDSUBST);
|
||||
target_str = tok_last( &tok );
|
||||
if (expand_one(target_str, EXPAND_SKIP_CMDSUBST)) {
|
||||
target = target_str.c_str();
|
||||
}
|
||||
/*
|
||||
Redirect filename may contain a cmdsubst.
|
||||
If so, it will be ignored/not flagged.
|
||||
|
|
117
parser.cpp
117
parser.cpp
|
@ -474,7 +474,7 @@ const wchar_t *parser_t::get_block_desc( int block ) const
|
|||
/**
|
||||
Returns 1 if the specified command is a builtin that may not be used in a pipeline
|
||||
*/
|
||||
static int parser_is_pipe_forbidden( wchar_t *word )
|
||||
static int parser_is_pipe_forbidden( const wcstring &word )
|
||||
{
|
||||
return contains( word,
|
||||
L"exec",
|
||||
|
@ -1394,7 +1394,8 @@ void parser_t::parse_job_argument_list( process_t *p,
|
|||
{
|
||||
int type = tok_last_type( tok );
|
||||
io_data_t *new_io;
|
||||
wchar_t *target = 0;
|
||||
wcstring target;
|
||||
bool has_target = false;
|
||||
wchar_t *end;
|
||||
|
||||
/*
|
||||
|
@ -1441,11 +1442,10 @@ void parser_t::parse_job_argument_list( process_t *p,
|
|||
{
|
||||
case TOK_STRING:
|
||||
{
|
||||
target = expand_one( j,
|
||||
wcsdup( tok_last( tok ) ),
|
||||
no_exec ? EXPAND_SKIP_VARIABLES : 0);
|
||||
target = tok_last( tok );
|
||||
has_target = expand_one(target, no_exec ? EXPAND_SKIP_VARIABLES : 0);
|
||||
|
||||
if( target == 0 && error_code == 0 )
|
||||
if( ! has_target && error_code == 0 )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
|
@ -1463,7 +1463,7 @@ void parser_t::parse_job_argument_list( process_t *p,
|
|||
tok_get_desc( tok_last_type(tok)) );
|
||||
}
|
||||
|
||||
if( target == 0 || wcslen( target )==0 )
|
||||
if( ! has_target || target.size() == 0 )
|
||||
{
|
||||
if( error_code == 0 )
|
||||
error( SYNTAX_ERROR,
|
||||
|
@ -1479,30 +1479,30 @@ void parser_t::parse_job_argument_list( process_t *p,
|
|||
case TOK_REDIRECT_APPEND:
|
||||
new_io->io_mode = IO_FILE;
|
||||
new_io->param2.flags = O_CREAT | O_APPEND | O_WRONLY;
|
||||
new_io->param1.filename = target;
|
||||
new_io->param1.filename = wcsdup(target.c_str()); // PCA LEAKS!
|
||||
break;
|
||||
|
||||
case TOK_REDIRECT_OUT:
|
||||
new_io->io_mode = IO_FILE;
|
||||
new_io->param2.flags = O_CREAT | O_WRONLY | O_TRUNC;
|
||||
new_io->param1.filename = target;
|
||||
new_io->param1.filename = wcsdup(target.c_str()); // PCA LEAKS!
|
||||
break;
|
||||
|
||||
case TOK_REDIRECT_NOCLOB:
|
||||
new_io->io_mode = IO_FILE;
|
||||
new_io->param2.flags = O_CREAT | O_EXCL | O_WRONLY;
|
||||
new_io->param1.filename = target;
|
||||
new_io->param1.filename = wcsdup(target.c_str()); // PCA LEAKS!
|
||||
break;
|
||||
|
||||
case TOK_REDIRECT_IN:
|
||||
new_io->io_mode = IO_FILE;
|
||||
new_io->param2.flags = O_RDONLY;
|
||||
new_io->param1.filename = target;
|
||||
new_io->param1.filename = wcsdup(target.c_str()); // PCA LEAKS!
|
||||
break;
|
||||
|
||||
case TOK_REDIRECT_FD:
|
||||
{
|
||||
if( wcscmp( target, L"-" ) == 0 )
|
||||
if( target == L"-" )
|
||||
{
|
||||
new_io->io_mode = IO_CLOSE;
|
||||
}
|
||||
|
@ -1513,7 +1513,7 @@ void parser_t::parse_job_argument_list( process_t *p,
|
|||
new_io->io_mode = IO_FD;
|
||||
errno = 0;
|
||||
|
||||
new_io->param1.old_fd = wcstol( target,
|
||||
new_io->param1.old_fd = wcstol( target.c_str(),
|
||||
&end,
|
||||
10 );
|
||||
|
||||
|
@ -1523,7 +1523,7 @@ void parser_t::parse_job_argument_list( process_t *p,
|
|||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
_(L"Requested redirection to something that is not a file descriptor %ls"),
|
||||
target );
|
||||
target.c_str() );
|
||||
|
||||
tok_next(tok);
|
||||
}
|
||||
|
@ -1628,7 +1628,8 @@ int parser_t::parse_job( process_t *p,
|
|||
|
||||
while( args.size() == 0 )
|
||||
{
|
||||
wchar_t *nxt=0;
|
||||
wcstring nxt;
|
||||
bool has_nxt = false;
|
||||
int consumed = 0; // Set to one if the command requires a second command, like e.g. while does
|
||||
int mark; // Use to save the position of the beginning of the token
|
||||
|
||||
|
@ -1636,11 +1637,10 @@ int parser_t::parse_job( process_t *p,
|
|||
{
|
||||
case TOK_STRING:
|
||||
{
|
||||
nxt = expand_one( j,
|
||||
wcsdup(tok_last( tok )),
|
||||
EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
|
||||
nxt = tok_last( tok );
|
||||
has_nxt = expand_one(nxt, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
|
||||
|
||||
if( nxt == 0 )
|
||||
if( ! has_nxt)
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
|
@ -1709,7 +1709,7 @@ int parser_t::parse_job( process_t *p,
|
|||
L"exec" ) )
|
||||
{
|
||||
int sw;
|
||||
int is_exec = (wcscmp( L"exec", nxt )==0);
|
||||
int is_exec = nxt == L"exec";
|
||||
|
||||
if( is_exec && (p != j->first_process) )
|
||||
{
|
||||
|
@ -1736,11 +1736,10 @@ int parser_t::parse_job( process_t *p,
|
|||
|
||||
consumed=1;
|
||||
|
||||
if( ( wcscmp( L"command", nxt )==0 ) ||
|
||||
( wcscmp( L"builtin", nxt )==0 ) )
|
||||
if( nxt == L"command" || nxt == L"builtin" )
|
||||
{
|
||||
use_function = 0;
|
||||
if( wcscmp( L"command", nxt )==0 )
|
||||
if( nxt == L"command" )
|
||||
{
|
||||
use_builtin = 0;
|
||||
use_command = 1;
|
||||
|
@ -1751,15 +1750,15 @@ int parser_t::parse_job( process_t *p,
|
|||
use_command = 0;
|
||||
}
|
||||
}
|
||||
else if( wcscmp( L"not", nxt )==0 )
|
||||
else if( nxt == L"not" )
|
||||
{
|
||||
job_set_flag( j, JOB_NEGATE, !job_get_flag( j, JOB_NEGATE ) );
|
||||
}
|
||||
else if( wcscmp( L"and", nxt )==0 )
|
||||
else if( nxt == L"and" )
|
||||
{
|
||||
job_set_flag( j, JOB_SKIP, proc_get_last_status());
|
||||
}
|
||||
else if( wcscmp( L"or", nxt )==0 )
|
||||
else if( nxt == L"or" )
|
||||
{
|
||||
job_set_flag( j, JOB_SKIP, !proc_get_last_status());
|
||||
}
|
||||
|
@ -1772,7 +1771,7 @@ int parser_t::parse_job( process_t *p,
|
|||
}
|
||||
}
|
||||
}
|
||||
else if( wcscmp( L"while", nxt ) ==0 )
|
||||
else if( nxt == L"while" )
|
||||
{
|
||||
int new_block = 0;
|
||||
tok_next( tok );
|
||||
|
@ -1801,7 +1800,7 @@ int parser_t::parse_job( process_t *p,
|
|||
is_new_block=1;
|
||||
|
||||
}
|
||||
else if( wcscmp( L"if", nxt ) ==0 )
|
||||
else if( nxt == L"if" )
|
||||
{
|
||||
tok_next( tok );
|
||||
|
||||
|
@ -1856,7 +1855,7 @@ int parser_t::parse_job( process_t *p,
|
|||
nxt_forbidden = (forbid == nxt);
|
||||
}
|
||||
|
||||
if( !nxt_forbidden && function_exists( nxt ) )
|
||||
if( !nxt_forbidden && has_nxt && function_exists( nxt.c_str() ) )
|
||||
{
|
||||
/*
|
||||
Check if we have reached the maximum recursion depth
|
||||
|
@ -2551,13 +2550,13 @@ int parser_t::eval( const wcstring &cmdStr, io_data_t *io, enum block_type_t blo
|
|||
/**
|
||||
\return the block type created by the specified builtin, or -1 on error.
|
||||
*/
|
||||
int parser_get_block_type( const wchar_t *cmd )
|
||||
int parser_get_block_type( const wcstring &cmd )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i=0; block_lookup[i].desc; i++ )
|
||||
{
|
||||
if( block_lookup[i].name && (wcscmp( block_lookup[i].name, cmd ) == 0) )
|
||||
if( block_lookup[i].name && cmd == block_lookup[i].name )
|
||||
{
|
||||
return block_lookup[i].type;
|
||||
}
|
||||
|
@ -2833,7 +2832,8 @@ int parser_t::test( const wchar_t * buff,
|
|||
/*
|
||||
The currently validated command.
|
||||
*/
|
||||
wchar_t *cmd=0;
|
||||
wcstring command;
|
||||
bool has_command = false;
|
||||
|
||||
CHECK( buff, 1 );
|
||||
|
||||
|
@ -2871,10 +2871,11 @@ int parser_t::test( const wchar_t * buff,
|
|||
had_cmd = 1;
|
||||
arg_count=0;
|
||||
|
||||
if( !(cmd = expand_one( context,
|
||||
wcsdup( tok_last( &tok ) ),
|
||||
EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES ) ) )
|
||||
command = tok_last(&tok);
|
||||
has_command = expand_one(command, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
|
||||
if( !has_command )
|
||||
{
|
||||
command = L"";
|
||||
err=1;
|
||||
if( out )
|
||||
{
|
||||
|
@ -2895,7 +2896,7 @@ int parser_t::test( const wchar_t * buff,
|
|||
command is needed, such as after 'and' or
|
||||
'while'
|
||||
*/
|
||||
if( contains( cmd,
|
||||
if( contains( command,
|
||||
L"end" ) )
|
||||
{
|
||||
err=1;
|
||||
|
@ -2915,14 +2916,14 @@ int parser_t::test( const wchar_t * buff,
|
|||
/*
|
||||
Decrement block count on end command
|
||||
*/
|
||||
if( wcscmp(cmd, L"end")==0)
|
||||
if( command == L"end")
|
||||
{
|
||||
tok_next( &tok );
|
||||
count--;
|
||||
tok_set_pos( &tok, mark );
|
||||
}
|
||||
|
||||
is_else = wcscmp(cmd, L"else")==0;
|
||||
is_else = (command == L"else");
|
||||
|
||||
/*
|
||||
Store the block level. This needs to be done
|
||||
|
@ -2937,7 +2938,7 @@ int parser_t::test( const wchar_t * buff,
|
|||
/*
|
||||
Handle block commands
|
||||
*/
|
||||
if( parser_keywords_is_block( cmd ) )
|
||||
if( parser_keywords_is_block( command ) )
|
||||
{
|
||||
if( count >= BLOCK_MAX_COUNT )
|
||||
{
|
||||
|
@ -2949,7 +2950,7 @@ int parser_t::test( const wchar_t * buff,
|
|||
}
|
||||
else
|
||||
{
|
||||
block_type[count] = parser_get_block_type( cmd );
|
||||
block_type[count] = parser_get_block_type( command );
|
||||
block_pos[count] = current_tokenizer_pos;
|
||||
tok_next( &tok );
|
||||
count++;
|
||||
|
@ -2963,13 +2964,13 @@ int parser_t::test( const wchar_t * buff,
|
|||
argument. If parser_skip_arguments is true, the
|
||||
second argument is optional.
|
||||
*/
|
||||
if( parser_keywords_is_subcommand( cmd ) && !parser_keywords_skip_arguments(cmd ) )
|
||||
if( parser_keywords_is_subcommand( command ) && !parser_keywords_skip_arguments(command ) )
|
||||
{
|
||||
needs_cmd = 1;
|
||||
had_cmd = 0;
|
||||
}
|
||||
|
||||
if( contains( cmd,
|
||||
if( contains( command,
|
||||
L"or",
|
||||
L"and" ) )
|
||||
{
|
||||
|
@ -2996,7 +2997,7 @@ int parser_t::test( const wchar_t * buff,
|
|||
are forbidden, including when using the exec
|
||||
builtin.
|
||||
*/
|
||||
if( parser_is_pipe_forbidden( cmd ) )
|
||||
if( parser_is_pipe_forbidden( command ) )
|
||||
{
|
||||
if( is_pipeline )
|
||||
{
|
||||
|
@ -3017,7 +3018,7 @@ int parser_t::test( const wchar_t * buff,
|
|||
/*
|
||||
Test that the case builtin is only used directly in a switch block
|
||||
*/
|
||||
if( wcscmp( L"case", cmd )==0 )
|
||||
if( command == L"case" )
|
||||
{
|
||||
if( !count || block_type[count-1]!=SWITCH )
|
||||
{
|
||||
|
@ -3040,7 +3041,7 @@ int parser_t::test( const wchar_t * buff,
|
|||
/*
|
||||
Test that the return bultin is only used within function definitions
|
||||
*/
|
||||
if( wcscmp( cmd, L"return" ) == 0 )
|
||||
if( command == L"return" )
|
||||
{
|
||||
int found_func=0;
|
||||
int i;
|
||||
|
@ -3061,18 +3062,14 @@ int parser_t::test( const wchar_t * buff,
|
|||
show the help.
|
||||
*/
|
||||
|
||||
wchar_t *first_arg;
|
||||
int old_pos = tok_get_pos( &tok );
|
||||
int is_help = 0;
|
||||
|
||||
tok_next( &tok );
|
||||
if( tok_last_type( &tok ) == TOK_STRING )
|
||||
{
|
||||
first_arg = expand_one( context,
|
||||
wcsdup( tok_last( &tok ) ),
|
||||
EXPAND_SKIP_CMDSUBST);
|
||||
|
||||
if( first_arg && parser_t::is_help( first_arg, 3) )
|
||||
wcstring first_arg = tok_last(&tok);
|
||||
if (expand_one(first_arg, EXPAND_SKIP_CMDSUBST) && parser_t::is_help( first_arg.c_str(), 3))
|
||||
{
|
||||
is_help = 1;
|
||||
}
|
||||
|
@ -3101,7 +3098,7 @@ int parser_t::test( const wchar_t * buff,
|
|||
/*
|
||||
Test that break and continue are only used within loop blocks
|
||||
*/
|
||||
if( contains( cmd, L"break", L"continue" ) )
|
||||
if( contains( command, L"break", L"continue" ) )
|
||||
{
|
||||
int found_loop=0;
|
||||
int i;
|
||||
|
@ -3123,18 +3120,14 @@ int parser_t::test( const wchar_t * buff,
|
|||
show the help.
|
||||
*/
|
||||
|
||||
wchar_t *first_arg;
|
||||
int old_pos = tok_get_pos( &tok );
|
||||
int is_help = 0;
|
||||
|
||||
tok_next( &tok );
|
||||
if( tok_last_type( &tok ) == TOK_STRING )
|
||||
{
|
||||
first_arg = expand_one( context,
|
||||
wcsdup( tok_last( &tok ) ),
|
||||
EXPAND_SKIP_CMDSUBST);
|
||||
|
||||
if( first_arg && parser_t::is_help( first_arg, 3 ) )
|
||||
wcstring first_arg = tok_last( &tok );
|
||||
if( expand_one(first_arg, EXPAND_SKIP_CMDSUBST) && parser_t::is_help( first_arg.c_str(), 3 ) )
|
||||
{
|
||||
is_help = 1;
|
||||
}
|
||||
|
@ -3161,7 +3154,7 @@ int parser_t::test( const wchar_t * buff,
|
|||
/*
|
||||
Test that else is only used directly in an if-block
|
||||
*/
|
||||
if( wcscmp( L"else", cmd )==0 )
|
||||
if( command == L"else" )
|
||||
{
|
||||
if( !count || block_type[count-1]!=IF )
|
||||
{
|
||||
|
@ -3213,13 +3206,13 @@ int parser_t::test( const wchar_t * buff,
|
|||
arg_count = -1;
|
||||
}
|
||||
|
||||
if( cmd )
|
||||
if( has_command )
|
||||
{
|
||||
|
||||
/*
|
||||
Try to make sure the second argument to 'for' is 'in'
|
||||
*/
|
||||
if( wcscmp( cmd, L"for" ) == 0 )
|
||||
if( command == L"for" )
|
||||
{
|
||||
if( arg_count == 1 )
|
||||
{
|
||||
|
@ -3418,7 +3411,7 @@ int parser_t::test( const wchar_t * buff,
|
|||
|
||||
if( end_of_cmd )
|
||||
{
|
||||
if( cmd && wcscmp( cmd, L"for" ) == 0 )
|
||||
if( has_command && command == L"for" )
|
||||
{
|
||||
if( arg_count >= 0 && arg_count < 2 )
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue