diff --git a/Makefile.in b/Makefile.in index 98634e8ac..11bd00ffc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -61,7 +61,7 @@ COMMON_OBJS := function.o builtin.o common.o complete.o env.o exec.o \ expand.o highlight.o history.o kill.o parser.o proc.o reader.o \ sanity.o tokenizer.o util.o wildcard.o wgetopt.o wutil.o input.o \ output.o intern.o env_universal.o env_universal_common.o \ - input_common.o event.o signal.o io.o translate.o + input_common.o event.o signal.o io.o translate.o parse_util.o # builtin_help.h exists, but builtin_help.c is autogenerated COMMON_OBJS_WITH_HEADER := builtin_help.o diff --git a/builtin.c b/builtin.c index 7e75a1429..67b405105 100644 --- a/builtin.c +++ b/builtin.c @@ -1733,8 +1733,8 @@ static int builtin_status( wchar_t **argv ) case 'h': builtin_print_help( argv[0], sb_err ); - break; - + return 0; + case 'i': mode = INTERACTIVE; break; diff --git a/builtin.h b/builtin.h index 725178713..02a0ddead 100644 --- a/builtin.h +++ b/builtin.h @@ -159,6 +159,8 @@ int builtin_ulimit(wchar_t **argv); */ int builtin_complete(wchar_t **argv); +const wchar_t *builtin_complete_get_temporary_buffer(); + /** This function works like wperror, but it prints its result into the sb_err string_buffer_t instead of to stderr. Used by the builtin diff --git a/builtin_commandline.c b/builtin_commandline.c index d69901ddf..224b7e7db 100644 --- a/builtin_commandline.c +++ b/builtin_commandline.c @@ -24,6 +24,7 @@ Functions used for implementing the commandline builtin. #include "input_common.h" #include "input.h" #include "translate.h" +#include "parse_util.h" /** Which part of the comandbuffer are we operating on @@ -48,6 +49,26 @@ enum } ; +/** + Returns the current commandline buffer. +*/ +static const wchar_t *get_buffer() +{ + const wchar_t *buff = builtin_complete_get_temporary_buffer(); + if( !buff ) + buff = reader_get_buffer(); + return buff; +} + +static int get_cursor_pos() +{ + const wchar_t *buff = builtin_complete_get_temporary_buffer(); + if( buff ) + return wcslen( buff ); + else + return reader_get_cursor_pos(); +} + /** Replace/append/insert the selection with/at/after the specified string. @@ -57,14 +78,14 @@ enum \param insert the string to insert \param append_mode can be one of REPLACE_MODE, INSERT_MODE or APPEND_MODE, affects the way the test update is performed */ -static void replace_part( wchar_t *begin, - wchar_t *end, +static void replace_part( const wchar_t *begin, + const wchar_t *end, wchar_t *insert, int append_mode ) { - wchar_t *buff = reader_get_buffer(); + const wchar_t *buff = get_buffer(); string_buffer_t out; - int out_pos=reader_get_cursor_pos(); + int out_pos=get_cursor_pos(); sb_init( &out ); @@ -88,7 +109,7 @@ static void replace_part( wchar_t *begin, } case INSERT_MODE: { - int cursor = reader_get_cursor_pos() -(begin-buff); + int cursor = get_cursor_pos() -(begin-buff); sb_append_substring( &out, begin, cursor ); sb_append( &out, insert ); sb_append_substring( &out, begin+cursor, end-begin-cursor ); @@ -109,8 +130,8 @@ static void replace_part( wchar_t *begin, \param cut_at_cursor whether printing should stop at the surrent cursor position \param tokenize whether the string should be tokenized, printing one string token on every line and skipping non-string tokens */ -static void write_part( wchar_t *begin, - wchar_t *end, +static void write_part( const wchar_t *begin, + const wchar_t *end, int cut_at_cursor, int tokenize ) { @@ -119,7 +140,7 @@ static void write_part( wchar_t *begin, wchar_t *buff; int pos; - pos = reader_get_cursor_pos()-(begin-reader_get_buffer()); + pos = get_cursor_pos()-(begin-get_buffer()); if( tokenize ) { @@ -184,7 +205,7 @@ int builtin_commandline( wchar_t **argv ) int tokenize = 0; - if( !reader_get_buffer() ) + if( !get_buffer() ) { sb_append2( sb_err, argv[0], @@ -429,32 +450,42 @@ int builtin_commandline( wchar_t **argv ) buffer_part = STRING_MODE; } - wchar_t *begin, *end; + const wchar_t *begin, *end; switch( buffer_part ) { case STRING_MODE: { - begin = reader_get_buffer(); + begin = get_buffer(); end = begin+wcslen(begin); break; } case PROCESS_MODE: { - reader_current_process_extent( &begin, &end ); + parse_util_process_extent( get_buffer(), + get_cursor_pos(), + &begin, + &end ); break; } case JOB_MODE: { - reader_current_job_extent( &begin, &end ); + parse_util_job_extent( get_buffer(), + get_cursor_pos(), + &begin, + &end ); break; } case TOKEN_MODE: { - reader_current_token_extent( &begin, &end, 0, 0 ); + parse_util_token_extent( get_buffer(), + get_cursor_pos(), + &begin, + &end, + 0, 0 ); break; } diff --git a/builtin_complete.c b/builtin_complete.c index ed9c1927f..b9947c1bd 100644 --- a/builtin_complete.c +++ b/builtin_complete.c @@ -19,8 +19,11 @@ Functions used for implementing the complete builtin. #include "complete.h" #include "wgetopt.h" #include "parser.h" +#include "reader.h" #include "translate.h" +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 @@ -235,6 +238,11 @@ static void builtin_complete_remove( array_list_t *cmd, } +const wchar_t *builtin_complete_get_temporary_buffer() +{ + return temporary_buffer; +} + int builtin_complete( wchar_t **argv ) { int res=0; @@ -247,9 +255,18 @@ int builtin_complete( wchar_t **argv ) array_list_t gnu_opt, old_opt; wchar_t *comp=L"", *desc=L"", *condition=L"", *load=0; + wchar_t *do_complete = 0; + array_list_t cmd; array_list_t path; + static int recursion_level=0; + + if( !is_interactive_session ) + { + debug( 1, _(L"%ls: Command only available in interactive sessions"), argv[0] ); + } + al_init( &cmd ); al_init( &path ); sb_init( &short_opt ); @@ -320,6 +337,10 @@ int builtin_complete( wchar_t **argv ) L"load", required_argument, 0, 'y' } , + { + L"do-complete", required_argument, 0, 'C' + } + , { 0, 0, 0, 0 } @@ -330,7 +351,7 @@ int builtin_complete( wchar_t **argv ) int opt = wgetopt_long( argc, argv, - L"a:c:p:s:l:o:d:frxeun:y:", + L"a:c:p:s:l:o:d:frxeun:y:C:", long_options, &opt_index ); if( opt == -1 ) @@ -410,8 +431,11 @@ int builtin_complete( wchar_t **argv ) case 'y': load = woptarg; break; - + case 'C': + do_complete = woptarg?woptarg:reader_get_buffer(); + break; + case '?': // builtin_print_help( argv[0], sb_err ); @@ -424,6 +448,40 @@ int builtin_complete( wchar_t **argv ) if( res != 0 ) { + } + else if( do_complete ) + { + array_list_t comp; + int i; + + const wchar_t *prev_temporary_buffer = temporary_buffer; + temporary_buffer = do_complete; + + if( recursion_level < 1 ) + { + recursion_level++; + + + al_init( &comp ); + + complete( do_complete, &comp ); + + for( i=0; icompleted = 1; } - io_buffer_destroy( io_buffer ); io_buffer=0; diff --git a/expand.c b/expand.c index 21e548c44..48ccbabd8 100644 --- a/expand.c +++ b/expand.c @@ -39,6 +39,7 @@ parameter expansion. #include "tokenizer.h" #include "complete.h" #include "translate.h" +#include "parse_util.h" /** Description for child process @@ -1154,105 +1155,23 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out ) return 1; } -int expand_locate_subshell( wchar_t *in, - wchar_t **begin, - wchar_t **end, - int allow_incomplete ) -{ - wchar_t *pos; - wchar_t prev=0; - int syntax_error=0; - int paran_count=0; - - wchar_t *paran_begin=0, *paran_end=0; - - for( pos=in; *pos; pos++ ) - { - if( prev != '\\' ) - { - if( wcschr( L"\'\"", *pos ) ) - { - wchar_t *end = quote_end( pos ); - if( end && *end) - { - pos=end; - } - else - break; - } - else - { - if( *pos == '(' ) - { - if(( paran_count == 0)&&(paran_begin==0)) - paran_begin = pos; - - paran_count++; - } - else if( *pos == ')' ) - { - paran_count--; - if( (paran_count == 0) && (paran_end == 0) ) - { - paran_end = pos; - break; - } - - if( paran_count < 0 ) - { - syntax_error = 1; - break; - } - } - } - - } - - prev = *pos; - } - - syntax_error |= (paran_count < 0 ); - syntax_error |= ((paran_count>0)&&(!allow_incomplete)); - - if( syntax_error ) - { - return -1; - } - - if( paran_begin == 0 ) - { - return 0; - } - - *begin = paran_begin; - *end = paran_count?in+wcslen(in):paran_end; - -/* assert( *begin >= in ); - assert( *begin < (in+wcslen(in) ) ); - assert( *end >= *begin ); - assert( *end < (in+wcslen(in) ) ); -*/ - return 1; - -} - /** Perform subshell expansion */ static int expand_subshell( wchar_t *in, array_list_t *out ) { - wchar_t *paran_begin=0, *paran_end=0; + const wchar_t *paran_begin=0, *paran_end=0; int len1, len2; wchar_t prev=0; wchar_t *subcmd; array_list_t sub_res, tail_expand; int i, j; - wchar_t *item_begin; + const wchar_t *item_begin; - switch( expand_locate_subshell(in, - ¶n_begin, - ¶n_end, - 0 ) ) + switch( parse_util_locate_cmdsubst(in, + ¶n_begin, + ¶n_end, + 0 ) ) { case -1: error( SYNTAX_ERROR, diff --git a/expand.h b/expand.h index a557af8ff..6065dc30c 100644 --- a/expand.h +++ b/expand.h @@ -182,20 +182,6 @@ wchar_t *expand_escape_variable( const wchar_t *in ); */ wchar_t *expand_tilde(wchar_t *in); -/** - Locate the first subshell in the specified string. - - \param in the string to search for subshells - \param begin the starting paranthesis of the subshell - \param end the ending paranthesis of the subshell - \param flags set this variable to ACCEPT_INCOMPLETE if in tab_completion mode - \return -1 on syntax error, 0 if no subshells exist and 1 on sucess -*/ -int expand_locate_subshell( wchar_t *in, - wchar_t **begin, - wchar_t **end, - int flags ); - /** Tokenize the specified string into the specified array_list_t. diff --git a/fish_pager.c b/fish_pager.c index 018f869d9..ffbe725d0 100644 --- a/fish_pager.c +++ b/fish_pager.c @@ -424,54 +424,54 @@ static void printed_length( wchar_t *str, else { - switch( *str ) - { - case L'\n': - case L'\b': - case L'\r': - case L'\e': - case L'\t': - case L'\\': - case L'&': - case L'$': - case L' ': - case L'#': - case L'^': - case L'<': - case L'>': - case L'(': - case L')': - case L'[': - case L']': - case L'{': - case L'}': - case L'?': - case L'*': - case L'|': - case L';': - case L':': - case L'\'': - case L'"': - case L'%': - case L'~': + switch( *str ) + { + case L'\n': + case L'\b': + case L'\r': + case L'\e': + case L'\t': + case L'\\': + case L'&': + case L'$': + case L' ': + case L'#': + case L'^': + case L'<': + case L'>': + case L'(': + case L')': + case L'[': + case L']': + case L'{': + case L'}': + case L'?': + case L'*': + case L'|': + case L';': + case L':': + case L'\'': + case L'"': + case L'%': + case L'~': - if( has_description ) - desc_len++; - else - comp_len+=2; - break; + if( has_description ) + desc_len++; + else + comp_len+=2; + break; - case COMPLETE_SEP: - has_description = 1; - break; + case COMPLETE_SEP: + has_description = 1; + break; - default: - if( has_description ) - desc_len+= wcwidth(*str); - else - comp_len+= wcwidth(*str); - break; - } + default: + if( has_description ) + desc_len+= wcwidth(*str); + else + comp_len+= wcwidth(*str); + break; + } } str++; diff --git a/function.c b/function.c index c9787cecc..7d174f367 100644 --- a/function.c +++ b/function.c @@ -86,16 +86,15 @@ void function_add( const wchar_t *name, { int i; wchar_t *cmd_end; + function_data_t *d; - if( function_exists( name ) ) function_remove( name ); - - - function_data_t *d = malloc( sizeof( function_data_t ) ); + d = malloc( sizeof( function_data_t ) ); d->definition_offset = count_lineno( parser_get_buffer(), current_block->tok_pos ); d->cmd = wcsdup( val ); + cmd_end = d->cmd + wcslen(d->cmd)-1; while( (cmd_end>d->cmd) && wcschr( L"\n\r\t ", *cmd_end ) ) { @@ -105,6 +104,7 @@ void function_add( const wchar_t *name, d->desc = desc?wcsdup( desc ):0; d->is_binding = is_binding; d->definition_file = reader_current_filename()?intern(reader_current_filename()):0; + hash_put( &function, intern(name), d ); for( i=0; i +#include +#include +#include +#include + +#include + +#include + +#include "util.h" +#include "wutil.h" +#include "common.h" +#include "tokenizer.h" +#include "parse_util.h" + +int parse_util_locate_cmdsubst( const wchar_t *in, + const wchar_t **begin, + const wchar_t **end, + int allow_incomplete ) +{ + const wchar_t *pos; + wchar_t prev=0; + int syntax_error=0; + int paran_count=0; + + const wchar_t *paran_begin=0, *paran_end=0; + + for( pos=in; *pos; pos++ ) + { + if( prev != '\\' ) + { + if( wcschr( L"\'\"", *pos ) ) + { + wchar_t *end = quote_end( pos ); + if( end && *end) + { + pos=end; + } + else + break; + } + else + { + if( *pos == '(' ) + { + if(( paran_count == 0)&&(paran_begin==0)) + paran_begin = pos; + + paran_count++; + } + else if( *pos == ')' ) + { + paran_count--; + if( (paran_count == 0) && (paran_end == 0) ) + { + paran_end = pos; + break; + } + + if( paran_count < 0 ) + { + syntax_error = 1; + break; + } + } + } + + } + + prev = *pos; + } + + syntax_error |= (paran_count < 0 ); + syntax_error |= ((paran_count>0)&&(!allow_incomplete)); + + if( syntax_error ) + { + return -1; + } + + if( paran_begin == 0 ) + { + return 0; + } + + *begin = paran_begin; + *end = paran_count?in+wcslen(in):paran_end; + +/* assert( *begin >= in ); + assert( *begin < (in+wcslen(in) ) ); + assert( *end >= *begin ); + assert( *end < (in+wcslen(in) ) ); +*/ + return 1; + +} + + +void parse_util_cmdsubst_extent( const wchar_t *buff, + int cursor_pos, + const wchar_t **a, + const wchar_t **b ) +{ + const wchar_t *begin, *end; + const wchar_t *pos; + + if( a ) + *a=0; + if( b ) + *b = 0; + + if( !buff ) + return; + + pos = buff; + + while( 1 ) + { + int bc, ec; + + if( parse_util_locate_cmdsubst( pos, + &begin, + &end, + 1 ) <= 0) + { + begin=buff; + end = buff + wcslen(buff); + break; + } + + if( !end ) + { + end = buff + wcslen(buff); + } + + bc = begin-buff; + ec = end-buff; + + if(( bc < cursor_pos ) && (ec >= cursor_pos) ) + { + begin++; + break; + } + pos = end+1; + } + if( a ) + *a = begin; + if( b ) + *b = end; +} + +/** + Get the beginning and end of the job or process definition under the cursor +*/ +static void job_or_process_extent( const wchar_t *buff, + int cursor_pos, + const wchar_t **a, + const wchar_t **b, + int process ) +{ + const wchar_t *begin, *end; + int pos; + wchar_t *buffcpy; + int finished=0; + + tokenizer tok; + + if( a ) + *a=0; + if( b ) + *b = 0; + + parse_util_cmdsubst_extent( buff, cursor_pos, &begin, &end ); + if( !end || !begin ) + return; + + pos = cursor_pos - (begin - buff); +// fwprintf( stderr, L"Subshell extent: %d %d %d\n", begin-buff, end-buff, pos ); + + if( a ) + { + *a = begin; + } + + if( b ) + { + *b = end; + } + + buffcpy = wcsndup( begin, end-begin ); + + if( !buffcpy ) + { + die_mem(); + } +// fwprintf( stderr, L"Strlen: %d\n", wcslen(buffcpy ) ); + + for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED ); + tok_has_next( &tok ) && !finished; + tok_next( &tok ) ) + { + int tok_begin = tok_get_pos( &tok ); +// fwprintf( stderr, L"."); + + switch( tok_last_type( &tok ) ) + { + case TOK_PIPE: + if( !process ) + break; + + case TOK_END: + case TOK_BACKGROUND: + { + +// fwprintf( stderr, L"New cmd at %d\n", tok_begin ); + + if( tok_begin >= pos ) + { + finished=1; + if( b ) + *b = buff + tok_begin; + } + else + { + if( a ) + *a = buff + tok_begin+1; + } + break; + + } + } + } + +// fwprintf( stderr, L"Res: %d %d\n", *a-buff, *b-buff ); + free( buffcpy); + + tok_destroy( &tok ); + +} + +void parse_util_process_extent( const wchar_t *buff, + int pos, + const wchar_t **a, + const wchar_t **b ) +{ + job_or_process_extent( buff, pos, a, b, 1 ); +} + +void parse_util_job_extent( const wchar_t *buff, + int pos, + const wchar_t **a, + const wchar_t **b ) +{ + job_or_process_extent( buff,pos,a, b, 0 ); +} + + +void parse_util_token_extent( const wchar_t *buff, + int cursor_pos, + const wchar_t **tok_begin, + const wchar_t **tok_end, + const wchar_t **prev_begin, + const wchar_t **prev_end ) +{ + const wchar_t *begin, *end; + int pos; + wchar_t *buffcpy; + + tokenizer tok; + + const wchar_t *a, *b, *pa, *pb; + + + a = b = pa = pb = 0; + + parse_util_cmdsubst_extent( buff, cursor_pos, &begin, &end ); + + if( !end || !begin ) + return; + + pos = cursor_pos - (begin - buff); + + a = buff + pos; + b = a; + pa = buff + pos; + pb = pa; + + assert( begin >= buff ); + assert( begin <= (buff+wcslen(buff) ) ); + assert( end >= begin ); + assert( end <= (buff+wcslen(buff) ) ); + + buffcpy = wcsndup( begin, end-begin ); + + if( !buffcpy ) + { + die_mem(); + } + + for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED ); + tok_has_next( &tok ); + tok_next( &tok ) ) + { + int tok_begin = tok_get_pos( &tok ); + int tok_end=tok_begin; + + /* + Calculate end of token + */ + if( tok_last_type( &tok ) == TOK_STRING ) + tok_end +=wcslen(tok_last(&tok)); + + /* + Cursor was before beginning of this token, means that the + cursor is between two tokens, so we set it to a zero element + string and break + */ + if( tok_begin > pos ) + { + a = b = buff + pos; + break; + } + + /* + If cursor is inside the token, this is the token we are + looking for. If so, set a and b and break + */ + if( tok_end >= pos ) + { + a = begin + tok_get_pos( &tok ); + b = a + wcslen(tok_last(&tok)); + +// fwprintf( stderr, L"Whee %ls\n", *a ); + + break; + } + + /* + Remember previous string token + */ + if( tok_last_type( &tok ) == TOK_STRING ) + { + pa = begin + tok_get_pos( &tok ); + pb = pa + wcslen(tok_last(&tok)); + } + } + + free( buffcpy); + + tok_destroy( &tok ); + + if( tok_begin ) + *tok_begin = a; + if( tok_end ) + *tok_end = b; + if( prev_begin ) + *prev_begin = pa; + if( prev_end ) + *prev_end = pb; + + assert( pa >= buff ); + assert( pa <= (buff+wcslen(buff) ) ); + assert( pb >= pa ); + assert( pb <= (buff+wcslen(buff) ) ); + +} + + + diff --git a/parse_util.h b/parse_util.h new file mode 100644 index 000000000..30f47ef85 --- /dev/null +++ b/parse_util.h @@ -0,0 +1,50 @@ +/** \file parse_util.h + + Various utility functions for parsing a command +*/ + +#ifndef FISH_PARSE_UTIL_H +#define FISH_PARSE_UTIL_H + +#include + +/** + Locate the first subshell in the specified string. + + \param in the string to search for subshells + \param begin the starting paranthesis of the subshell + \param end the ending paranthesis of the subshell + \param flags set this variable to ACCEPT_INCOMPLETE if in tab_completion mode + \return -1 on syntax error, 0 if no subshells exist and 1 on sucess +*/ + +int parse_util_locate_cmdsubst( const wchar_t *in, + const wchar_t **begin, + const wchar_t **end, + int allow_incomplete ); + + +void parse_util_cmdsubst_extent( const wchar_t *buff, + int cursor_pos, + const wchar_t **a, + const wchar_t **b ); + +void parse_util_process_extent( const wchar_t *buff, + int pos, + const wchar_t **a, + const wchar_t **b ); + + +void parse_util_job_extent( const wchar_t *buff, + int pos, + const wchar_t **a, + const wchar_t **b ); + +void parse_util_token_extent( const wchar_t *buff, + int cursor_pos, + const wchar_t **tok_begin, + const wchar_t **tok_end, + const wchar_t **prev_begin, + const wchar_t **prev_end ); + +#endif diff --git a/parser.c b/parser.c index 9e9354eb0..372b9e110 100644 --- a/parser.c +++ b/parser.c @@ -265,7 +265,7 @@ static int current_tokenizer_pos; block_t *current_block=0; /** List of called functions, used to help prevent infinite recursion */ -static array_list_t forbidden_function; +static array_list_t *forbidden_function; /** String index where the current job started. @@ -726,7 +726,7 @@ void parser_forbid_function( wchar_t *function ) if( function ) debug( 2, L"Forbid %ls\n", function ); */ - al_push( &forbidden_function, function?wcsdup(function):0 ); + al_push( forbidden_function, function?wcsdup(function):0 ); } void parser_allow_function() @@ -735,7 +735,7 @@ void parser_allow_function() if( al_peek( &forbidden_function) ) debug( 2, L"Allow %ls\n", al_peek( &forbidden_function) ); */ - free( (void *) al_pop( &forbidden_function ) ); + free( (void *) al_pop( forbidden_function ) ); } void error( int ec, int p, const wchar_t *str, ... ) @@ -848,7 +848,8 @@ void parser_init() { al_init( &profile_data); } - al_init( &forbidden_function ); + forbidden_function = al_new(); + } /** @@ -924,14 +925,15 @@ void parser_destroy() al_destroy( &profile_data ); } - al_destroy( &forbidden_function ); - if( lineinfo ) { sb_destroy( lineinfo ); free(lineinfo ); lineinfo = 0; } + + al_destroy( forbidden_function ); + free( forbidden_function ); } @@ -1236,7 +1238,7 @@ wchar_t *parser_current_line() */ if( !is_interactive || is_function() || (current_line_width!=0) ) { - // Workaround since it seems impossible to print 0 copies of a character using printf + // Workaround since it seems impossible to print 0 copies of a character using %*lc if( offset+current_line_width ) { sb_printf( lineinfo, @@ -1875,7 +1877,7 @@ static int parse_job( process_t *p, int nxt_forbidden; wchar_t *forbid; - forbid = (wchar_t *)(al_get_count( &forbidden_function)?al_peek( &forbidden_function ):0); + forbid = (wchar_t *)(al_get_count( forbidden_function)?al_peek( forbidden_function ):0); nxt_forbidden = forbid && (wcscmp( forbid, nxt) == 0 ); /* @@ -1887,7 +1889,7 @@ static int parse_job( process_t *p, /* Check if we have reached the maximum recursion depth */ - if( al_get_count( &forbidden_function ) > MAX_RECURSION_DEPTH ) + if( al_get_count( forbidden_function ) > MAX_RECURSION_DEPTH ) { error( SYNTAX_ERROR, tok_get_pos( tok ), @@ -2351,6 +2353,15 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type ) tokenizer *previous_tokenizer=current_tokenizer; block_t *start_current_block = current_block; io_data_t *prev_io = block_io; + array_list_t *prev_forbidden = forbidden_function; + + if( block_type == SUBST ) + { + forbidden_function = al_new(); + } + + forbid_count = al_get_count( forbidden_function ); + block_io = io; job_reap( 0 ); @@ -2387,7 +2398,6 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type ) parser_push_block( block_type ); - forbid_count = al_get_count( &forbidden_function ); tok_init( current_tokenizer, cmd, 0 ); error_code = 0; @@ -2447,19 +2457,28 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type ) tok_destroy( current_tokenizer ); free( current_tokenizer ); - while( forbid_count < al_get_count( &forbidden_function )) + while( al_get_count( forbidden_function ) > forbid_count ) parser_allow_function(); + if( block_type == SUBST ) + { + al_destroy( forbidden_function ); + free( forbidden_function ); + } + + /* + Restore previous eval state + */ + forbidden_function = prev_forbidden; current_tokenizer=previous_tokenizer; + block_io = prev_io; + eval_level--; code=error_code; error_code=0; - block_io = prev_io; - - eval_level--; - job_reap( 0 ); + return code; } diff --git a/proc.c b/proc.c index b6e1ca104..ed20daf3e 100644 --- a/proc.c +++ b/proc.c @@ -388,7 +388,7 @@ static void handle_child_status( pid_t pid, int status ) "Process %d is %ls from job %ls\n", (int) pid, p->actual_cmd, j->command ); write( 2, mess, strlen(mess )); -*/ +*/ mark_process_status ( j, p, status); if( p->completed && prev != 0 ) diff --git a/reader.c b/reader.c index b79005d09..8d6b5a2c6 100644 --- a/reader.c +++ b/reader.c @@ -80,6 +80,7 @@ commence. #include "output.h" #include "signal.h" #include "translate.h" +#include "parse_util.h" /** Maximum length of prefix string when printing completion @@ -1691,274 +1692,17 @@ void reader_sanity_check() } } -void reader_current_subshell_extent( wchar_t **a, wchar_t **b ) -{ - wchar_t *begin, *end; - wchar_t *pos; - - if( a ) - *a=0; - if( b ) - *b = 0; - - if( !data ) - return; - - pos = data->buff; - - while( 1 ) - { - int bc, ec; - - if( expand_locate_subshell( pos, - &begin, - &end, - 1 ) <= 0) - { - begin=data->buff; - end = data->buff + wcslen(data->buff); - break; - } - - if( !end ) - { - end = data->buff + wcslen(data->buff); - } - - bc = begin-data->buff; - ec = end-data->buff; - - if(( bc < data->buff_pos ) && (ec >= data->buff_pos) ) - { - begin++; - break; - } - pos = end+1; - } - if( a ) - *a = begin; - if( b ) - *b = end; -} - -/** - Get the beginning and dend of the job or process definition under the cursor -*/ -static void reader_current_job_or_process_extent( wchar_t **a, - wchar_t **b, - int process ) -{ - wchar_t *begin, *end; - int pos; - wchar_t *buffcpy; - int finished=0; - - tokenizer tok; - - if( a ) - *a=0; - if( b ) - *b = 0; - - reader_current_subshell_extent( &begin, &end ); - if( !end || !begin ) - return; - - pos = data->buff_pos - (begin - data->buff); -// fwprintf( stderr, L"Subshell extent: %d %d %d\n", begin-data->buff, end-data->buff, pos ); - - if( a ) - { - *a = begin; - } - - if( b ) - { - *b = end; - } - - buffcpy = wcsndup( begin, end-begin ); - - if( !buffcpy ) - { - die_mem(); - } -// fwprintf( stderr, L"Strlen: %d\n", wcslen(buffcpy ) ); - - for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED ); - tok_has_next( &tok ) && !finished; - tok_next( &tok ) ) - { - int tok_begin = tok_get_pos( &tok ); -// fwprintf( stderr, L"."); - - switch( tok_last_type( &tok ) ) - { - case TOK_PIPE: - if( !process ) - break; - - case TOK_END: - case TOK_BACKGROUND: - { - -// fwprintf( stderr, L"New cmd at %d\n", tok_begin ); - - if( tok_begin >= pos ) - { - finished=1; - if( b ) - *b = data->buff + tok_begin; - } - else - { - if( a ) - *a = data->buff + tok_begin+1; - } - break; - - } - } - } - -// fwprintf( stderr, L"Res: %d %d\n", *a-data->buff, *b-data->buff ); - free( buffcpy); - - tok_destroy( &tok ); - -} - -void reader_current_process_extent( wchar_t **a, wchar_t **b ) -{ - reader_current_job_or_process_extent( a, b, 1 ); -} - -void reader_current_job_extent( wchar_t **a, wchar_t **b ) -{ - reader_current_job_or_process_extent( a, b, 0 ); -} - - -void reader_current_token_extent( wchar_t **tok_begin, - wchar_t **tok_end, - wchar_t **prev_begin, - wchar_t **prev_end ) -{ - wchar_t *begin, *end; - int pos; - wchar_t *buffcpy; - - tokenizer tok; - - wchar_t *a, *b, *pa, *pb; - - - a = b = pa = pb = 0; - - reader_current_subshell_extent( &begin, &end ); - - if( !end || !begin ) - return; - - pos = data->buff_pos - (begin - data->buff); - - a = data->buff + pos; - b = a; - pa = data->buff + pos; - pb = pa; - - assert( begin >= data->buff ); - assert( begin <= (data->buff+wcslen(data->buff) ) ); - assert( end >= begin ); - assert( end <= (data->buff+wcslen(data->buff) ) ); - - buffcpy = wcsndup( begin, end-begin ); - - if( !buffcpy ) - { - die_mem(); - } - - for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED ); - tok_has_next( &tok ); - tok_next( &tok ) ) - { - int tok_begin = tok_get_pos( &tok ); - int tok_end=tok_begin; - - /* - Calculate end of token - */ - if( tok_last_type( &tok ) == TOK_STRING ) - tok_end +=wcslen(tok_last(&tok)); - - /* - Cursor was before beginning of this token, means that the - cursor is between two tokens, so we set it to a zero element - string and break - */ - if( tok_begin > pos ) - { - a = b = data->buff + pos; - break; - } - - /* - If cursor is inside the token, this is the token we are - looking for. If so, set a and b and break - */ - if( tok_end >= pos ) - { - a = begin + tok_get_pos( &tok ); - b = a + wcslen(tok_last(&tok)); - -// fwprintf( stderr, L"Whee %ls\n", *a ); - - break; - } - - /* - Remember previous string token - */ - if( tok_last_type( &tok ) == TOK_STRING ) - { - pa = begin + tok_get_pos( &tok ); - pb = pa + wcslen(tok_last(&tok)); - } - } - - free( buffcpy); - - tok_destroy( &tok ); - - if( tok_begin ) - *tok_begin = a; - if( tok_end ) - *tok_end = b; - if( prev_begin ) - *prev_begin = pa; - if( prev_end ) - *prev_end = pb; - - assert( pa >= data->buff ); - assert( pa <= (data->buff+wcslen(data->buff) ) ); - assert( pb >= pa ); - assert( pb <= (data->buff+wcslen(data->buff) ) ); - -} - - void reader_replace_current_token( wchar_t *new_token ) { - wchar_t *begin, *end; + const wchar_t *begin, *end; string_buffer_t sb; int new_pos; /* Find current token */ - reader_current_token_extent( &begin, &end, 0, 0 ); + parse_util_token_extent( data->buff, data->buff_pos, &begin, &end, 0, 0 ); if( !begin || !end ) return; @@ -2018,9 +1762,9 @@ static int contains( const wchar_t *needle, */ static void reset_token_history() { - wchar_t *begin, *end; + const wchar_t *begin, *end; - reader_current_token_extent( &begin, &end, 0, 0 ); + parse_util_token_extent( data->buff, data->buff_pos, &begin, &end, 0, 0 ); if( begin ) { wcslcpy(data->search_buff, begin, end-begin+1); @@ -2718,10 +2462,10 @@ wchar_t *reader_readline() if( comp_empty ) { - wchar_t *begin, *end; + const wchar_t *begin, *end; wchar_t *buffcpy; - reader_current_subshell_extent( &begin, &end ); + parse_util_cmdsubst_extent( data->buff, data->buff_pos, &begin, &end ); int len = data->buff_pos - (data->buff - begin); buffcpy = wcsndup( begin, len ); diff --git a/reader.h b/reader.h index de0d6b5ef..3f8b52f36 100644 --- a/reader.h +++ b/reader.h @@ -152,27 +152,6 @@ void reader_set_prompt( wchar_t *prompt ); */ int exit_status(); -/** - Find the beginning and the end of the current subshell -*/ -void reader_current_subshell_extent( wchar_t **a, wchar_t **b ); - -/** - Find the beginning and the end of the job under the cursor -*/ -void reader_current_job_extent( wchar_t **a, wchar_t **b ); - -/** - Find the beginning and the end of the process under the cursor -*/ -void reader_current_process_extent( wchar_t **a, wchar_t **b ); - -/** - Find the beginning and the end of the token under the curor and the token before the cursor -*/ - -void reader_current_token_extent( wchar_t **a, wchar_t **b, wchar_t **pa, wchar_t **pb ); - /** Replace the current token with the specified string */