[2819] in BarnOwl Developers

home help back first fref pref prev next nref lref last post

[PATCH 1/2] Add owl_quote_arg and owl_string_append_quoted_arg

daemon@ATHENA.MIT.EDU (David Benjamin)
Wed Dec 15 00:01:56 2010

From: David Benjamin <davidben@MIT.EDU>
To: barnowl-dev@mit.edu
Date: Wed, 15 Dec 2010 00:00:41 -0500

Also add unit tests. We don't appear to have an equivalent of
BarnOwl::quote in C that actually works.
---
 tester.c |   37 +++++++++++++++++++++++++++++++++++++
 util.c   |   41 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+), 0 deletions(-)

diff --git a/tester.c b/tester.c
index 41ba0d8..8678d74 100644
--- a/tester.c
+++ b/tester.c
@@ -175,6 +175,43 @@ int owl_util_regtest(void)
   FAIL_UNLESS("skiptokens 5",
               !strcmp("c d e", skiptokens("a \"'\" c d e", 2)));
 
+#define CHECK_QUOTING(desc, unquoted, quoted)		\
+  do {							\
+      int __argc;					\
+      char *__quoted = owl_arg_quote(unquoted);		\
+      char **__argv;					\
+      FAIL_UNLESS(desc, !strcmp(quoted, __quoted));	\
+      __argv = owl_parseline(__quoted, &__argc);	\
+      FAIL_UNLESS(desc " - arg count", __argc == 1);	\
+      FAIL_UNLESS(desc " - parsed",			\
+		  !strcmp(__argv[0], unquoted));	\
+      owl_parse_delete(__argv, __argc);			\
+      owl_free(__quoted);				\
+    } while (0)
+
+  CHECK_QUOTING("boring text", "mango", "mango");
+  CHECK_QUOTING("spaces", "mangos are tasty", "'mangos are tasty'");
+  CHECK_QUOTING("single quotes", "mango's", "\"mango's\"");
+  CHECK_QUOTING("double quotes", "he said \"mangos are tasty\"",
+		"'he said \"mangos are tasty\"'");
+  CHECK_QUOTING("both quotes",
+		"he said \"mango's are tasty even when you put in "
+		"a random apostrophe\"",
+		"\"he said \"'\"'\"mango's are tasty even when you put in "
+		"a random apostrophe\"'\"'\"\"");
+  CHECK_QUOTING("quote monster", "'\"\"'\"'''\"",
+		"\""
+		"'"
+		"\"'\"'\""
+		"\"'\"'\""
+		"'"
+		"\"'\"'\""
+		"'"
+		"'"
+		"'"
+		"\"'\"'\""
+		"\"");
+
   /* if (numfailed) printf("*** WARNING: failures encountered with owl_util\n"); */
   printf("# END testing owl_util (%d failures)\n", numfailed);
   return(numfailed);
diff --git a/util.c b/util.c
index bd842df..3a233c9 100644
--- a/util.c
+++ b/util.c
@@ -233,6 +233,47 @@ char **owl_parseline(const char *line, int *argc)
   return(argv);
 }
 
+/* Appends a quoted version of arg suitable for placing in a
+ * command-line to a GString. Does not append a space. */
+void owl_string_append_quoted_arg(GString *buf, const char *arg)
+{
+  const char *argp;
+  if (arg[0] == '\0') {
+    /* Quote the empty string. */
+    g_string_append(buf, "''");
+  } else if (strcspn(arg, "'\" \n\t") == strlen(arg)) {
+    /* If there are no nasty characters, return as-is. */
+    g_string_append(buf, arg);
+  } else if (!strchr(arg, '\'')) {
+    /* Single-quote if possible. */
+    g_string_append_c(buf, '\'');
+    g_string_append(buf, arg);
+    g_string_append_c(buf, '\'');
+  } else {
+    /* Nasty case: double-quote, but change all internal "s to "'"'"
+     * so that they are single-quoted because we're too cool for
+     * backslashes.
+     */
+    g_string_append_c(buf, '"');
+    for (argp = arg; *argp; argp++) {
+      if (*argp == '"')
+	g_string_append(buf, "\"'\"'\"");
+      else
+	g_string_append_c(buf, *argp);
+    }
+    g_string_append_c(buf, '"');
+  }
+}
+
+/* Returns a quoted version of arg suitable for placing in a
+ * command-line. Result should be freed with owl_free. */
+char *owl_arg_quote(const char *arg)
+{
+  GString *buf = g_string_new("");;
+  owl_string_append_quoted_arg(buf, arg);
+  return g_string_free(buf, FALSE);
+}
+
 /* caller must free the return */
 char *owl_util_minutes_to_timestr(int in)
 {
-- 
1.7.3.3.399.g06ddf


home help back first fref pref prev next nref lref last post