--- /dev/null
+Return-Path: <amdragon@mit.edu>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by olra.theworths.org (Postfix) with ESMTP id 8032A431FB6\r
+ for <notmuch@notmuchmail.org>; Sun, 30 Dec 2012 21:52:24 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.7\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
+ tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+ by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id V-44hOknVuAK for <notmuch@notmuchmail.org>;\r
+ Sun, 30 Dec 2012 21:52:23 -0800 (PST)\r
+Received: from dmz-mailsec-scanner-7.mit.edu (DMZ-MAILSEC-SCANNER-7.MIT.EDU\r
+ [18.7.68.36])\r
+ by olra.theworths.org (Postfix) with ESMTP id 1836E431FAF\r
+ for <notmuch@notmuchmail.org>; Sun, 30 Dec 2012 21:52:23 -0800 (PST)\r
+X-AuditID: 12074424-b7f4e6d0000004ca-7e-50e128149662\r
+Received: from mailhub-auth-1.mit.edu ( [18.9.21.35])\r
+ by dmz-mailsec-scanner-7.mit.edu (Symantec Messaging Gateway) with SMTP\r
+ id 3C.80.01226.41821E05; Mon, 31 Dec 2012 00:52:20 -0500 (EST)\r
+Received: from outgoing.mit.edu (OUTGOING-AUTH.MIT.EDU [18.7.22.103])\r
+ by mailhub-auth-1.mit.edu (8.13.8/8.9.2) with ESMTP id qBV5qKr4025387; \r
+ Mon, 31 Dec 2012 00:52:20 -0500\r
+Received: from awakening.csail.mit.edu (awakening.csail.mit.edu [18.26.4.91])\r
+ (authenticated bits=0)\r
+ (User authenticated as amdragon@ATHENA.MIT.EDU)\r
+ by outgoing.mit.edu (8.13.6/8.12.4) with ESMTP id qBV5qHf6006487\r
+ (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NOT);\r
+ Mon, 31 Dec 2012 00:52:19 -0500 (EST)\r
+Received: from amthrax by awakening.csail.mit.edu with local (Exim 4.80)\r
+ (envelope-from <amdragon@mit.edu>)\r
+ id 1TpYIL-0007eU-Ay; Mon, 31 Dec 2012 00:52:17 -0500\r
+From: Austin Clements <amdragon@MIT.EDU>\r
+To: Tomi Ollila <tomi.ollila@iki.fi>, notmuch@notmuchmail.org\r
+Subject: Re: [PATCH v3 2/5] util: Function to parse boolean term queries\r
+In-Reply-To: <m2han4sepu.fsf@guru.guru-group.fi>\r
+References: <1356719189-2837-1-git-send-email-amdragon@mit.edu>\r
+ <1356719189-2837-3-git-send-email-amdragon@mit.edu>\r
+ <m2han4sepu.fsf@guru.guru-group.fi>\r
+User-Agent: Notmuch/0.14+236~gf64406d (http://notmuchmail.org) Emacs/23.4.1\r
+ (i486-pc-linux-gnu)\r
+Date: Mon, 31 Dec 2012 00:52:17 -0500\r
+Message-ID: <87a9sulqem.fsf@awakening.csail.mit.edu>\r
+MIME-Version: 1.0\r
+Content-Type: text/plain; charset=us-ascii\r
+X-Brightmail-Tracker:\r
+ H4sIAAAAAAAAA+NgFnrAIsWRmVeSWpSXmKPExsUixCmqrCui8TDAYP9Ma4vrN2cyW7xZOY/V\r
+ gcnj8NeFLB7PVt1iDmCK4rJJSc3JLEst0rdL4Mo49ymmYLdixctfr5gbGA9IdjFycEgImEhs\r
+ OVzWxcgJZIpJXLi3ng3EFhLYxyjR+IGzi5ELyN7AKLHw0QMmCOcik8SiyQ0sEM4SRompvcvZ\r
+ QVrYBDQktu1fzghiiwjYSlxZcpIVxBYW8JDYuPEsE4jNKWAg8ej0U3aI5umMEi1rHoIlRAXi\r
+ JZ7f+8YCYrMIqErMXb6ZGcTmBTpv3b1J7BC2oMTJmU/AapgFtCRu/HvJNIFRYBaS1CwkqQWM\r
+ TKsYZVNyq3RzEzNzilOTdYuTE/PyUot0zfVyM0v0UlNKNzGCApLdRWUHY/MhpUOMAhyMSjy8\r
+ G/4/CBBiTSwrrsw9xCjJwaQkyquu/DBAiC8pP6UyI7E4I76oNCe1+BCjBAezkgjv0XlA5bwp\r
+ iZVVqUX5MClpDhYlcd7rKTf9hQTSE0tSs1NTC1KLYLIyHBxKErxa6kBDBYtS01Mr0jJzShDS\r
+ TBycIMN5gIabgtTwFhck5hZnpkPkTzEqSonzioEkBEASGaV5cL2whPGKURzoFWFeIZAqHmCy\r
+ get+BTSYCWiwFgPI1cUliQgpqQZGj/5foq4lzgzHljXNUprd0utrdLRePXbiI84oibNxsSkt\r
+ j5+8emDRt/+Nnc8jWZkzrNUxbZ+zCvQTVob9nidut2jv4iMzN3PuzpfVsp/y5OKit00WV/5w\r
+ XFlz/n4lo23u7UnzfNes+dL3qtXzghLDhV/VTLMjKsuCGNU8jt7d6exqPGfxvVg7JZbijERD\r
+ Leai4kQA9lwoOfMCAAA=\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Mon, 31 Dec 2012 05:52:24 -0000\r
+\r
+On Sat, 29 Dec 2012, Tomi Ollila <tomi.ollila@iki.fi> wrote:\r
+> On Fri, Dec 28 2012, Austin Clements <amdragon@MIT.EDU> wrote:\r
+>\r
+>> This parses the subset of Xapian's boolean term quoting rules that are\r
+>> used by make_boolean_term. This is provided as a generic string\r
+>> utility, but will be used shortly in notmuch restore to parse and\r
+>> optimize for ID queries.\r
+>> ---\r
+>> util/string-util.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+>> util/string-util.h | 11 +++++++++++\r
+>> 2 files changed, 66 insertions(+)\r
+>>\r
+>> diff --git a/util/string-util.c b/util/string-util.c\r
+>> index e4bea21..83b4953 100644\r
+>> --- a/util/string-util.c\r
+>> +++ b/util/string-util.c\r
+>> @@ -96,3 +96,58 @@ make_boolean_term (void *ctx, const char *prefix, const char *term,\r
+>> \r
+>> return 0;\r
+>> }\r
+>> +\r
+>> +int\r
+>> +parse_boolean_term (void *ctx, const char *str,\r
+>> + char **prefix_out, char **term_out)\r
+>> +{\r
+>> + *prefix_out = *term_out = NULL;\r
+>> +\r
+>> + /* Parse prefix */\r
+>> + const char *pos = strchr (str, ':');\r
+>> + if (! pos)\r
+>> + goto FAIL;\r
+>> + *prefix_out = talloc_strndup (ctx, str, pos - str);\r
+>> + ++pos;\r
+>> +\r
+>> + /* Implement de-quoting compatible with make_boolean_term. */\r
+>> + if (*pos == '"') {\r
+>> + char *out = talloc_array (ctx, char, strlen (pos));\r
+>> + int closed = 0;\r
+>> + *term_out = out;\r
+>> + /* Skip the opening quote, find the closing quote, and\r
+>> + * un-double doubled internal quotes. */\r
+>> + for (++pos; *pos; ) {\r
+>> + if (*pos == '"') {\r
+>> + ++pos;\r
+>> + if (*pos != '"') {\r
+>> + /* Found the closing quote. */\r
+>> + closed = 1;\r
+>> + break;\r
+>> + }\r
+>> + }\r
+>> + *out++ = *pos++;\r
+>> + }\r
+>> + /* Did the term terminate without a closing quote or is there\r
+>> + * trailing text after the closing quote? */\r
+>> + if (!closed || *pos)\r
+>> + goto FAIL;\r
+>> + *out = '\0';\r
+>> + } else {\r
+>> + const char *start = pos;\r
+>> + /* Check for text after the boolean term. */\r
+>> + while (*pos > ' ' && *pos != ')')\r
+>> + ++pos;\r
+>> + if (*pos)\r
+>> + goto FAIL;\r
+>\r
+> Mark pointed out a good case about trailing whitespace -- It would be nice\r
+> if the core were lenient for such cases. I personally remember once wasting\r
+> hours of work by just failing to notice trailing whitespace in one system\r
+> so this subject is sensitive to me...\r
+\r
+Will do.\r
+\r
+> Another thing I saw earlyer today: make_boolean_term() checks\r
+>\r
+> if (*in <= ' ' || *in == ')' || *in == '"' || (unsigned char)*in > 127)\r
+>\r
+> but here the check is only\r
+>\r
+> while (*pos > ' ' && *pos != ')')\r
+>\r
+> I wonder whether it matters...\r
+\r
+This is correct in a conservative way. We quote things that we don't\r
+strictly need to quote (for example, a double quote in the middle of a\r
+term doesn't actually require the term to be quoted, but we do anyway),\r
+but we look for the end of an unquoted term in exactly the same way\r
+Xapian does.\r
+\r
+> Everyting else looks good to me.\r
+>\r
+>\r
+> Tomi\r
+>\r
+>> + /* No trailing text; dup the string so the caller can free\r
+>> + * it. */\r
+>> + *term_out = talloc_strdup (ctx, start);\r
+>> + }\r
+>> + return 0;\r
+>> +\r
+>> + FAIL:\r
+>> + talloc_free (*prefix_out);\r
+>> + talloc_free (*term_out);\r
+>> + return 1;\r
+>> +}\r
+>> diff --git a/util/string-util.h b/util/string-util.h\r
+>> index b8844a3..43d49d0 100644\r
+>> --- a/util/string-util.h\r
+>> +++ b/util/string-util.h\r
+>> @@ -33,4 +33,15 @@ char *strtok_len (char *s, const char *delim, size_t *len);\r
+>> int make_boolean_term (void *talloc_ctx, const char *prefix, const char *term,\r
+>> char **buf, size_t *len);\r
+>> \r
+>> +/* Parse a boolean term query produced by make_boolean_term, returning\r
+>> + * the prefix in *prefix_out and the term in *term_out. *prefix_out\r
+>> + * and *term_out will be talloc'd with context ctx.\r
+>> + *\r
+>> + * Return: 0 on success, non-zero on parse error (including trailing\r
+>> + * data in str).\r
+>> + */\r
+>> +int\r
+>> +parse_boolean_term (void *ctx, const char *str,\r
+>> + char **prefix_out, char **term_out);\r
+>> +\r
+>> #endif\r
+>> -- \r
+>> 1.7.10.4\r
+>>\r
+>> _______________________________________________\r
+>> notmuch mailing list\r
+>> notmuch@notmuchmail.org\r
+>> http://notmuchmail.org/mailman/listinfo/notmuch\r