From b410c09291edfd6dad93fb5275363ee8f30b4bb1 Mon Sep 17 00:00:00 2001 From: Daniel Carl Date: Wed, 4 Jun 2014 23:08:19 +0200 Subject: [PATCH] Allow to escape ~user expansion with \ char. --- src/ex.c | 48 +++++++++++++++--------------------------------- src/util.c | 36 ++++++++++++++++++++++++++++-------- src/util.h | 3 ++- 3 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/ex.c b/src/ex.c index 81167da..b34a7e0 100644 --- a/src/ex.c +++ b/src/ex.c @@ -644,46 +644,28 @@ static gboolean parse_lhs(const char **input, ExArg *arg) */ static gboolean parse_rhs(const char **input, ExArg *arg) { - char quote = '\\'; - int expflags = UTIL_EXP_TILDE|UTIL_EXP_DOLLAR|UTIL_EXP_SPECIAL; + int expflags, flags; if (!*input || !**input) { return false; } + flags = expflags = (arg->flags & EX_FLAG_EXP) + ? UTIL_EXP_TILDE|UTIL_EXP_DOLLAR|UTIL_EXP_SPECIAL + : 0; + /* get char until the end of command */ while (**input && **input != '\n' && **input != '|') { - /* if we find a backslash this escapes the next char */ - if (**input == quote) { - /* move pointer to the next char */ - (*input)++; - if (!*input) { - /* if input ends here - use only the backslash */ - g_string_append_c(arg->rhs, quote); - } else if (**input == '|' || **input == '%') { - /* escaped char becomes only char */ - g_string_append_c(arg->rhs, **input); - } else { - /* put escape char and next char into the result string */ - g_string_append_c(arg->rhs, quote); - g_string_append_c(arg->rhs, **input); - } - } else { /* unquoted char */ - /* check for expansion placeholder */ - if (arg->flags & EX_FLAG_EXP) { - util_parse_expansion(input, arg->rhs, expflags); - - if (VB_IS_SPACE(**input)) { - /* add tilde expansion for next loop needs to be first - * char or to be after a space */ - expflags |= UTIL_EXP_TILDE; - } else { - /* remove tile expansion for next loop */ - expflags &= ~UTIL_EXP_TILDE; - } - } else { - g_string_append_c(arg->rhs, **input); - } + /* check for expansion placeholder */ + util_parse_expansion(input, arg->rhs, flags, "|~$%"); + + if (VB_IS_SPACE(**input)) { + /* add tilde expansion for next loop needs to be first char or to + * be after a space */ + flags = expflags; + } else { + /* remove tile expansion for next loop */ + flags &= ~UTIL_EXP_TILDE; } (*input)++; } diff --git a/src/util.c b/src/util.c index 69c2b59..404d205 100644 --- a/src/util.c +++ b/src/util.c @@ -352,7 +352,7 @@ char *util_expand(const char *src, int expflags) int flags = expflags; while (**input) { - util_parse_expansion(input, dst, flags); + util_parse_expansion(input, dst, flags, "~$%"); if (VB_IS_SEPARATOR(**input)) { /* after space the tilde expansion is allowed */ flags = expflags; @@ -376,15 +376,17 @@ char *util_expand(const char *src, int expflags) * not expanded char. If no expansion pattern was found, the first char is * appended to given GString. * - * @input: String pointer with the content to be parsed. - * @str: GString that will be filled with expanded content. - * @flags Flags that determine which expansion are processed. + * @input: String pointer with the content to be parsed. + * @str: GString that will be filled with expanded content. + * @flags Flags that determine which expansion are processed. + * @quoteable String of chars that are allowed to be escaped by \. * Returns true if input started with expandable pattern. */ -gboolean util_parse_expansion(const char **input, GString *str, int flags) +gboolean util_parse_expansion(const char **input, GString *str, int flags, + const char *quoteable) { GString *name; - const char *env, *prev; + const char *env, *prev, quote = '\\'; struct passwd *pwd; gboolean expanded = false; @@ -461,8 +463,26 @@ gboolean util_parse_expansion(const char **input, GString *str, int flags) if (!expanded) { /* restore the pointer position if no expansion was found */ *input = prev; - /* take the char like it is */ - g_string_append_c(str, **input); + + /* handle escaping of quoteable chars */ + if (**input == quote) { + /* move pointer to the next char */ + (*input)++; + if (!*input) { + /* if input ends here - use only the quote char */ + g_string_append_c(str, quote); + } else if (strchr(quoteable, **input)) { + /* escaped char becomes only char */ + g_string_append_c(str, **input); + } else { + /* put escape char and next char into the result string */ + g_string_append_c(str, quote); + g_string_append_c(str, **input); + } + } else { + /* take the char like it is */ + g_string_append_c(str, **input); + } } return expanded; diff --git a/src/util.h b/src/util.h index 237f0ea..5c7b4d4 100644 --- a/src/util.h +++ b/src/util.h @@ -47,7 +47,8 @@ char *util_str_replace(const char* search, const char* replace, const char* stri gboolean util_create_tmp_file(const char *content, char **file); char *util_build_path(const char *path, const char *dir); char *util_expand(const char *src, int expflags); -gboolean util_parse_expansion(const char **input, GString *str, int flags); +gboolean util_parse_expansion(const char **input, GString *str, int flags, + const char *quoteable); gboolean util_fill_completion(GtkListStore *store, const char *input, GList *src); #endif /* end of include guard: _UTIL_H */ -- 2.20.1