From 5db1e9cdbb526b138207cc7f802d73abbfc284cb Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Wed, 5 Mar 2014 15:20:53 +0000 Subject: [PATCH] Properly handle quoted strings in command parser. --- tts.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- ttsrc.sample | 6 ++++-- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/tts.c b/tts.c index 4510298..ba6b37a 100644 --- a/tts.c +++ b/tts.c @@ -2418,19 +2418,51 @@ const WCHAR *p, *q; for (;;) { ptrdiff_t sz; + int qskip = 0; + /* Skip leading whitespace */ while (ISSPACE(*p)) p++; + /* End of string - no more arguments */ if (!*p) break; q = p; - /* Find the next seperator */ - while (!ISSPACE(*q) && *q) - q++; + if (*q == '"') { + /* Quoted string - scan for end of string */ + int isbsl = 0; + p++; + while (*++q) { + /* Handle escaping with backslash; currently works but the \ isn't + * removed from the string. + */ + if (*q == '\\') { + isbsl = 1; + continue; + } + + if (!isbsl && (*q == '"')) + break; + + isbsl = 0; + } + /* At this point, *q == '"'. If it's NUL instead, then the + * string was not terminated with a closing '"' before the end + * of the line. We could give an error here, but it seems + * more useful to just accept it. + */ + if (*q == '"') + qskip = 1; + } else { + /* Not quoted - just find the next whitespace */ + while (!ISSPACE(*q) && *q) + q++; + } + + /* Copy the argument (which is sz bytes long) into the result array */ sz = (q - p); *res = realloc(*res, sizeof(WCHAR *) * (ntoks + 1)); (*res)[ntoks] = malloc(sizeof(WCHAR) * sz + 1); @@ -2438,9 +2470,16 @@ const WCHAR *p, *q; (*res)[ntoks][sz] = 0; ntoks++; + if (qskip) + q += qskip; + while (ISSPACE(*q)) q++; + /* + * q is the start of the next token (with leading whitespace); reset + * p to process the next argument. + */ if (!*q) break; p = q; diff --git a/ttsrc.sample b/ttsrc.sample index bfbc0a5..af6f67a 100644 --- a/ttsrc.sample +++ b/ttsrc.sample @@ -15,11 +15,13 @@ #### Miscellaneous options # # If set, show billable time in each daily summary. + #set show_billable 1 # If this is set, and a newly added entry contains this string, the entry wil -# be automatically marked as non-billable. The string can only be a single -# word and must not be put in quotes. +# be automatically marked as non-billable. If the string contains whitespace, +# it should be wrapped in "quote marks". + #set auto_non_billable [INT] #### Bindings