Allow to escape ~user expansion with \ char.
authorDaniel Carl <danielcarl@gmx.de>
Wed, 4 Jun 2014 21:08:19 +0000 (23:08 +0200)
committerDaniel Carl <danielcarl@gmx.de>
Wed, 4 Jun 2014 21:08:19 +0000 (23:08 +0200)
src/ex.c
src/util.c
src/util.h

index 81167da..b34a7e0 100644 (file)
--- 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)++;
     }
index 69c2b59..404d205 100644 (file)
@@ -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;
index 237f0ea..5c7b4d4 100644 (file)
@@ -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 */