[2819] in BarnOwl Developers
[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