Migrated off of old variant of expand_one that used halloc

This commit is contained in:
ridiculousfish 2012-01-31 21:30:09 -08:00
parent 409f70c7f3
commit 0b4b6c498d
4 changed files with 63 additions and 114 deletions

View file

@ -1809,47 +1809,6 @@ int expand_string2( const wcstring &input, std::vector<completion_t> &output, in
return res; 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) { bool expand_one(wcstring &string, int flags) {
std::vector<completion_t> completions; std::vector<completion_t> completions;
bool result = false; bool result = false;

View file

@ -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 expands to more than one string. This is used for expanding command
names. names.
If \c context is non-null, the returning string ill be registered \param inout_str The parameter to expand in-place
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 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 \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 ); bool expand_one( wcstring &inout_str, int flag );
/** /**

View file

@ -772,7 +772,8 @@ void tokenize( const wchar_t * const buff, int * const color, const int pos, arr
break; break;
} }
wchar_t *target=0; wcstring target_str;
const wchar_t *target=NULL;
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_REDIRECTION; color[ tok_get_pos( &tok ) ] = HIGHLIGHT_REDIRECTION;
tok_next( &tok ); tok_next( &tok );
@ -785,7 +786,10 @@ void tokenize( const wchar_t * const buff, int * const color, const int pos, arr
{ {
case TOK_STRING: 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. Redirect filename may contain a cmdsubst.
If so, it will be ignored/not flagged. If so, it will be ignored/not flagged.

View file

@ -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 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, return contains( word,
L"exec", L"exec",
@ -1394,7 +1394,8 @@ void parser_t::parse_job_argument_list( process_t *p,
{ {
int type = tok_last_type( tok ); int type = tok_last_type( tok );
io_data_t *new_io; io_data_t *new_io;
wchar_t *target = 0; wcstring target;
bool has_target = false;
wchar_t *end; wchar_t *end;
/* /*
@ -1441,11 +1442,10 @@ void parser_t::parse_job_argument_list( process_t *p,
{ {
case TOK_STRING: case TOK_STRING:
{ {
target = expand_one( j, target = tok_last( tok );
wcsdup( tok_last( tok ) ), has_target = expand_one(target, no_exec ? EXPAND_SKIP_VARIABLES : 0);
no_exec ? EXPAND_SKIP_VARIABLES : 0);
if( target == 0 && error_code == 0 ) if( ! has_target && error_code == 0 )
{ {
error( SYNTAX_ERROR, error( SYNTAX_ERROR,
tok_get_pos( tok ), 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)) ); tok_get_desc( tok_last_type(tok)) );
} }
if( target == 0 || wcslen( target )==0 ) if( ! has_target || target.size() == 0 )
{ {
if( error_code == 0 ) if( error_code == 0 )
error( SYNTAX_ERROR, error( SYNTAX_ERROR,
@ -1479,30 +1479,30 @@ void parser_t::parse_job_argument_list( process_t *p,
case TOK_REDIRECT_APPEND: case TOK_REDIRECT_APPEND:
new_io->io_mode = IO_FILE; new_io->io_mode = IO_FILE;
new_io->param2.flags = O_CREAT | O_APPEND | O_WRONLY; 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; break;
case TOK_REDIRECT_OUT: case TOK_REDIRECT_OUT:
new_io->io_mode = IO_FILE; new_io->io_mode = IO_FILE;
new_io->param2.flags = O_CREAT | O_WRONLY | O_TRUNC; 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; break;
case TOK_REDIRECT_NOCLOB: case TOK_REDIRECT_NOCLOB:
new_io->io_mode = IO_FILE; new_io->io_mode = IO_FILE;
new_io->param2.flags = O_CREAT | O_EXCL | O_WRONLY; 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; break;
case TOK_REDIRECT_IN: case TOK_REDIRECT_IN:
new_io->io_mode = IO_FILE; new_io->io_mode = IO_FILE;
new_io->param2.flags = O_RDONLY; new_io->param2.flags = O_RDONLY;
new_io->param1.filename = target; new_io->param1.filename = wcsdup(target.c_str()); // PCA LEAKS!
break; break;
case TOK_REDIRECT_FD: case TOK_REDIRECT_FD:
{ {
if( wcscmp( target, L"-" ) == 0 ) if( target == L"-" )
{ {
new_io->io_mode = IO_CLOSE; 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; new_io->io_mode = IO_FD;
errno = 0; errno = 0;
new_io->param1.old_fd = wcstol( target, new_io->param1.old_fd = wcstol( target.c_str(),
&end, &end,
10 ); 10 );
@ -1523,7 +1523,7 @@ void parser_t::parse_job_argument_list( process_t *p,
error( SYNTAX_ERROR, error( SYNTAX_ERROR,
tok_get_pos( tok ), tok_get_pos( tok ),
_(L"Requested redirection to something that is not a file descriptor %ls"), _(L"Requested redirection to something that is not a file descriptor %ls"),
target ); target.c_str() );
tok_next(tok); tok_next(tok);
} }
@ -1628,7 +1628,8 @@ int parser_t::parse_job( process_t *p,
while( args.size() == 0 ) 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 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 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: case TOK_STRING:
{ {
nxt = expand_one( j, nxt = tok_last( tok );
wcsdup(tok_last( tok )), has_nxt = expand_one(nxt, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
if( nxt == 0 ) if( ! has_nxt)
{ {
error( SYNTAX_ERROR, error( SYNTAX_ERROR,
tok_get_pos( tok ), tok_get_pos( tok ),
@ -1709,7 +1709,7 @@ int parser_t::parse_job( process_t *p,
L"exec" ) ) L"exec" ) )
{ {
int sw; int sw;
int is_exec = (wcscmp( L"exec", nxt )==0); int is_exec = nxt == L"exec";
if( is_exec && (p != j->first_process) ) if( is_exec && (p != j->first_process) )
{ {
@ -1736,11 +1736,10 @@ int parser_t::parse_job( process_t *p,
consumed=1; consumed=1;
if( ( wcscmp( L"command", nxt )==0 ) || if( nxt == L"command" || nxt == L"builtin" )
( wcscmp( L"builtin", nxt )==0 ) )
{ {
use_function = 0; use_function = 0;
if( wcscmp( L"command", nxt )==0 ) if( nxt == L"command" )
{ {
use_builtin = 0; use_builtin = 0;
use_command = 1; use_command = 1;
@ -1751,15 +1750,15 @@ int parser_t::parse_job( process_t *p,
use_command = 0; 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 ) ); 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()); 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()); 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; int new_block = 0;
tok_next( tok ); tok_next( tok );
@ -1801,7 +1800,7 @@ int parser_t::parse_job( process_t *p,
is_new_block=1; is_new_block=1;
} }
else if( wcscmp( L"if", nxt ) ==0 ) else if( nxt == L"if" )
{ {
tok_next( tok ); tok_next( tok );
@ -1856,7 +1855,7 @@ int parser_t::parse_job( process_t *p,
nxt_forbidden = (forbid == nxt); 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 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. \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; int i;
for( i=0; block_lookup[i].desc; 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; return block_lookup[i].type;
} }
@ -2833,7 +2832,8 @@ int parser_t::test( const wchar_t * buff,
/* /*
The currently validated command. The currently validated command.
*/ */
wchar_t *cmd=0; wcstring command;
bool has_command = false;
CHECK( buff, 1 ); CHECK( buff, 1 );
@ -2871,10 +2871,11 @@ int parser_t::test( const wchar_t * buff,
had_cmd = 1; had_cmd = 1;
arg_count=0; arg_count=0;
if( !(cmd = expand_one( context, command = tok_last(&tok);
wcsdup( tok_last( &tok ) ), has_command = expand_one(command, EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES ) ) ) if( !has_command )
{ {
command = L"";
err=1; err=1;
if( out ) if( out )
{ {
@ -2895,7 +2896,7 @@ int parser_t::test( const wchar_t * buff,
command is needed, such as after 'and' or command is needed, such as after 'and' or
'while' 'while'
*/ */
if( contains( cmd, if( contains( command,
L"end" ) ) L"end" ) )
{ {
err=1; err=1;
@ -2915,14 +2916,14 @@ int parser_t::test( const wchar_t * buff,
/* /*
Decrement block count on end command Decrement block count on end command
*/ */
if( wcscmp(cmd, L"end")==0) if( command == L"end")
{ {
tok_next( &tok ); tok_next( &tok );
count--; count--;
tok_set_pos( &tok, mark ); 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 Store the block level. This needs to be done
@ -2937,7 +2938,7 @@ int parser_t::test( const wchar_t * buff,
/* /*
Handle block commands Handle block commands
*/ */
if( parser_keywords_is_block( cmd ) ) if( parser_keywords_is_block( command ) )
{ {
if( count >= BLOCK_MAX_COUNT ) if( count >= BLOCK_MAX_COUNT )
{ {
@ -2949,7 +2950,7 @@ int parser_t::test( const wchar_t * buff,
} }
else else
{ {
block_type[count] = parser_get_block_type( cmd ); block_type[count] = parser_get_block_type( command );
block_pos[count] = current_tokenizer_pos; block_pos[count] = current_tokenizer_pos;
tok_next( &tok ); tok_next( &tok );
count++; count++;
@ -2963,13 +2964,13 @@ int parser_t::test( const wchar_t * buff,
argument. If parser_skip_arguments is true, the argument. If parser_skip_arguments is true, the
second argument is optional. 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; needs_cmd = 1;
had_cmd = 0; had_cmd = 0;
} }
if( contains( cmd, if( contains( command,
L"or", L"or",
L"and" ) ) L"and" ) )
{ {
@ -2996,7 +2997,7 @@ int parser_t::test( const wchar_t * buff,
are forbidden, including when using the exec are forbidden, including when using the exec
builtin. builtin.
*/ */
if( parser_is_pipe_forbidden( cmd ) ) if( parser_is_pipe_forbidden( command ) )
{ {
if( is_pipeline ) 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 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 ) 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 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 found_func=0;
int i; int i;
@ -3061,18 +3062,14 @@ int parser_t::test( const wchar_t * buff,
show the help. show the help.
*/ */
wchar_t *first_arg;
int old_pos = tok_get_pos( &tok ); int old_pos = tok_get_pos( &tok );
int is_help = 0; int is_help = 0;
tok_next( &tok ); tok_next( &tok );
if( tok_last_type( &tok ) == TOK_STRING ) if( tok_last_type( &tok ) == TOK_STRING )
{ {
first_arg = expand_one( context, wcstring first_arg = tok_last(&tok);
wcsdup( tok_last( &tok ) ), if (expand_one(first_arg, EXPAND_SKIP_CMDSUBST) && parser_t::is_help( first_arg.c_str(), 3))
EXPAND_SKIP_CMDSUBST);
if( first_arg && parser_t::is_help( first_arg, 3) )
{ {
is_help = 1; 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 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 found_loop=0;
int i; int i;
@ -3123,18 +3120,14 @@ int parser_t::test( const wchar_t * buff,
show the help. show the help.
*/ */
wchar_t *first_arg;
int old_pos = tok_get_pos( &tok ); int old_pos = tok_get_pos( &tok );
int is_help = 0; int is_help = 0;
tok_next( &tok ); tok_next( &tok );
if( tok_last_type( &tok ) == TOK_STRING ) if( tok_last_type( &tok ) == TOK_STRING )
{ {
first_arg = expand_one( context, wcstring first_arg = tok_last( &tok );
wcsdup( tok_last( &tok ) ), if( expand_one(first_arg, EXPAND_SKIP_CMDSUBST) && parser_t::is_help( first_arg.c_str(), 3 ) )
EXPAND_SKIP_CMDSUBST);
if( first_arg && parser_t::is_help( first_arg, 3 ) )
{ {
is_help = 1; 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 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 ) if( !count || block_type[count-1]!=IF )
{ {
@ -3213,13 +3206,13 @@ int parser_t::test( const wchar_t * buff,
arg_count = -1; arg_count = -1;
} }
if( cmd ) if( has_command )
{ {
/* /*
Try to make sure the second argument to 'for' is 'in' 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 ) if( arg_count == 1 )
{ {
@ -3418,7 +3411,7 @@ int parser_t::test( const wchar_t * buff,
if( end_of_cmd ) if( end_of_cmd )
{ {
if( cmd && wcscmp( cmd, L"for" ) == 0 ) if( has_command && command == L"for" )
{ {
if( arg_count >= 0 && arg_count < 2 ) if( arg_count >= 0 && arg_count < 2 )
{ {