diff --git a/common.c b/common.c index e743f632e..a3d536671 100644 --- a/common.c +++ b/common.c @@ -551,12 +551,34 @@ int my_wcswidth( const wchar_t *c ) return res; } -wchar_t *quote_end( const wchar_t *in ) +const wchar_t *quote_end( const wchar_t *pos ) { - return wcschr( in+1, *in ); + wchar_t c = *pos; + + while( 1 ) + { + pos++; + + if( !*pos ) + return 0; + + if( *pos == L'\\') + { + pos++; + } + else + { + if( *pos == c ) + { + return pos; + } + } + } + return 0; + } - + const wchar_t *wsetlocale(int category, const wchar_t *locale) { @@ -1137,6 +1159,30 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special ) */ case 1: { + if( c == L'\\' ) + { + switch( in[++in_pos] ) + { + case L'\'': + { + in[out_pos]=in[in_pos]; + break; + } + + case 0: + { + free(in); + return 0; + } + + default: + { + in[out_pos++] = L'\\'; + in[out_pos]= in[in_pos]; + } + } + + } if( c == L'\'' ) { in[out_pos] = INTERNAL_SEPARATOR; @@ -1175,11 +1221,12 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special ) } case L'$': + case '"': { in[out_pos]=in[in_pos]; break; } - + default: { in[out_pos++] = L'\\'; diff --git a/common.h b/common.h index 4208291cc..8bbdc9e1e 100644 --- a/common.h +++ b/common.h @@ -190,7 +190,7 @@ int my_wcswidth( const wchar_t *c ); \param in the position of the opening quote */ -wchar_t *quote_end( const wchar_t *in ); +const wchar_t *quote_end( const wchar_t *in ); /** A call to this function will reset the error counter. Some diff --git a/doc_src/doc.hdr b/doc_src/doc.hdr index 7af9f7256..82db951ec 100644 --- a/doc_src/doc.hdr +++ b/doc_src/doc.hdr @@ -69,10 +69,13 @@ happens, the user can write a parameter within quotes, either ' (single quote) or " (double quote). There is one important difference between single quoted and double quoted strings: When using double quoted string, variable expansion still -takes place. Other than that, a quoted parameter will not be -parameter expanded, may contain spaces, and escape sequences are -ignored. Single quotes have no special meaning withing double quotes -and vice versa. +takes place. Other than that, a quoted parameter will not be parameter +expanded, may contain spaces, and escape sequences are ignored. The +only backslash escape accepted within single quotes is \\', which +escapes a single quote. The only backslash escapes accepted within +double quotes are \\", which escapes a double quote, and \\$, which +escapes a dollar character. Single quotes have no special meaning +withing double quotes and vice versa. Example: @@ -82,7 +85,7 @@ Will remove the file 'cumbersome filename.txt', while rm cumbersome filename.txt -would remove the two files 'cumbersome' and 'filenmae.txt'. +would remove the two files 'cumbersome' and 'filename.txt'. \subsection escapes Escaping characters diff --git a/reader.c b/reader.c index d255c85f6..89404a6e1 100644 --- a/reader.c +++ b/reader.c @@ -1220,7 +1220,7 @@ static wchar_t get_quote( wchar_t *cmd, int l ) if( cmd[i] == L'\'' || cmd[i] == L'\"' ) { - wchar_t *end = quote_end( &cmd[i] ); + const wchar_t *end = quote_end( &cmd[i] ); //fwprintf( stderr, L"Jump %d\n", end-cmd ); if(( end == 0 ) || (!*end) || (end-cmd > l)) { diff --git a/tokenizer.c b/tokenizer.c index 435281b7b..b274b222a 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -272,11 +272,11 @@ static void read_string( tokenizer *tok ) case L'"': { - wchar_t *end = quote_end( tok->buff ); + const wchar_t *end = quote_end( tok->buff ); tok->last_quote = *tok->buff; if( end ) { - tok->buff=end; + tok->buff=(wchar_t *)end; } else { @@ -311,10 +311,10 @@ static void read_string( tokenizer *tok ) case L'\'': case L'\"': { - wchar_t *end = quote_end( tok->buff ); + const wchar_t *end = quote_end( tok->buff ); if( end ) { - tok->buff=end; + tok->buff=(wchar_t *)end; } else do_loop = 0;