[RFC PATCH 2/3] Compile the date/time parser into notmuch library
authorJani Nikula <jani@nikula.org>
Wed, 10 Aug 2011 10:22:06 +0000 (10:22 +0000)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:39:15 +0000 (09:39 -0800)
39/b28b5a9921a028bd4b446044847460f71193ce [new file with mode: 0644]

diff --git a/39/b28b5a9921a028bd4b446044847460f71193ce b/39/b28b5a9921a028bd4b446044847460f71193ce
new file mode 100644 (file)
index 0000000..29a581b
--- /dev/null
@@ -0,0 +1,950 @@
+Return-Path: <jani@nikula.org>\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 AA331429E34\r
+       for <notmuch@notmuchmail.org>; Wed, 10 Aug 2011 03:23:46 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References"\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 EqsqxWvrYV13 for <notmuch@notmuchmail.org>;\r
+       Wed, 10 Aug 2011 03:23:42 -0700 (PDT)\r
+Received: from mail-qy0-f181.google.com (mail-qy0-f181.google.com\r
+       [209.85.216.181]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
+       (No client certificate requested)\r
+       by olra.theworths.org (Postfix) with ESMTPS id C2ECC429E33\r
+       for <notmuch@notmuchmail.org>; Wed, 10 Aug 2011 03:23:41 -0700 (PDT)\r
+Received: by qyk34 with SMTP id 34so596577qyk.5\r
+       for <notmuch@notmuchmail.org>; Wed, 10 Aug 2011 03:22:21 -0700 (PDT)\r
+Received: by 10.229.160.12 with SMTP id l12mr47462qcx.258.1312971741415;\r
+       Wed, 10 Aug 2011 03:22:21 -0700 (PDT)\r
+Received: from localhost (nikula.org [92.243.24.172])\r
+       by mx.google.com with ESMTPS id s14sm710886qct.30.2011.08.10.03.22.17\r
+       (version=TLSv1/SSLv3 cipher=OTHER);\r
+       Wed, 10 Aug 2011 03:22:19 -0700 (PDT)\r
+From: Jani Nikula <jani@nikula.org>\r
+To: notmuch@notmuchmail.org\r
+Subject: [RFC PATCH 2/3] Compile the date/time parser into notmuch library\r
+Date: Wed, 10 Aug 2011 10:22:06 +0000\r
+Message-Id:\r
+ <09761de1bad20ecc80888a7dd472bcd6a14d504b.1312964528.git.jani@nikula.org>\r
+X-Mailer: git-send-email 1.7.1\r
+In-Reply-To: <cover.1312964528.git.jani@nikula.org>\r
+References: <cover.1312964528.git.jani@nikula.org>\r
+In-Reply-To: <cover.1312964528.git.jani@nikula.org>\r
+References: <cover.1312964528.git.jani@nikula.org>\r
+Cc: amdragon@mit.edu\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: Wed, 10 Aug 2011 10:23:47 -0000\r
+\r
+From: Michal Sojka <sojkam1@fel.cvut.cz>\r
+\r
+---\r
+ Makefile.local     |    3 +\r
+ configure          |    8 ++\r
+ lib/Makefile.local |    5 +-\r
+ lib/config.h       |   45 +++++++++++++\r
+ lib/getdate.c      |  185 +++++++++++++++++++++++++++-------------------------\r
+ lib/getdate.h      |    9 +++\r
+ lib/getdate.y      |   15 ++++-\r
+ 7 files changed, 178 insertions(+), 92 deletions(-)\r
+ create mode 100644 lib/config.h\r
+\r
+diff --git a/Makefile.local b/Makefile.local\r
+index e3d4d03..3da9ad9 100644\r
+--- a/Makefile.local\r
++++ b/Makefile.local\r
+@@ -234,6 +234,9 @@ quiet ?= $($(shell echo $1 | sed -e s'/ .*//'))\r
+ %.o: %.c $(global_deps)\r
+       $(call quiet,CC $(CFLAGS)) -c $(FINAL_CFLAGS) $< -o $@\r
\r
++%.c: %.y\r
++      $(call quiet,YACC $(YFLAGS)) $(YFLAGS) $< -o $@\r
++\r
+ .deps/%.d: %.c $(global_deps)\r
+       @set -e; rm -f $@; mkdir -p $$(dirname $@) ; \\r
+       $(CC) -M $(CPPFLAGS) $(FINAL_CFLAGS) $< > $@.$$$$ 2>/dev/null ; \\r
+diff --git a/configure b/configure\r
+index 3999ce8..f385c79 100755\r
+--- a/configure\r
++++ b/configure\r
+@@ -25,9 +25,11 @@ fi\r
+ # environment variables)\r
+ CC=${CC:-gcc}\r
+ CXX=${CXX:-g++}\r
++YACC=${YACC:-yacc}\r
+ CFLAGS=${CFLAGS:--O2}\r
+ CXXFLAGS=${CXXFLAGS:-\$(CFLAGS)}\r
+ LDFLAGS=${LDFLAGS:-}\r
++YFLAGS=${YFLAGS}\r
+ XAPIAN_CONFIG=${XAPIAN_CONFIG:-xapian-config}\r
\r
+ # We don't allow the EMACS or GZIP Makefile variables inherit values\r
+@@ -571,6 +573,9 @@ CC = ${CC}\r
+ # The C++ compiler to use\r
+ CXX = ${CXX}\r
\r
++# The parser generator to use\r
++YACC = ${YACC}\r
++\r
+ # Command to execute emacs from Makefiles\r
+ EMACS = emacs --quick\r
\r
+@@ -589,6 +594,9 @@ WARN_CXXFLAGS=${WARN_CXXFLAGS}\r
+ # Flags to enable warnings when using the C compiler\r
+ WARN_CFLAGS=${WARN_CFLAGS}\r
\r
++# Default FLAGS for parser generator (can be overridden by user such as "make YFLAGS=-y")\r
++YFLAGS = ${YFLAGS}\r
++\r
+ # The prefix to which notmuch should be installed\r
+ # Note: If you change this value here, be sure to ensure that the\r
+ # LIBDIR_IN_LDCONFIG value below is still set correctly.\r
+diff --git a/lib/Makefile.local b/lib/Makefile.local\r
+index fbc2f6a..a1c234f 100644\r
+--- a/lib/Makefile.local\r
++++ b/lib/Makefile.local\r
+@@ -56,7 +56,10 @@ libnotmuch_c_srcs =         \\r
+       $(dir)/messages.c       \\r
+       $(dir)/sha1.c           \\r
+       $(dir)/tags.c           \\r
+-      $(dir)/xutil.c\r
++      $(dir)/xutil.c          \\r
++      $(dir)/getdate.c        \\r
++      $(dir)/c-ctype.c        \\r
++      $(dir)/gettime.c\r
\r
+ libnotmuch_cxx_srcs =         \\r
+       $(dir)/database.cc      \\r
+diff --git a/lib/config.h b/lib/config.h\r
+new file mode 100644\r
+index 0000000..e8bc5b7\r
+--- /dev/null\r
++++ b/lib/config.h\r
+@@ -0,0 +1,45 @@\r
++/* lib/config.h.  Generated from config.hin by configure.  */\r
++/* lib/config.hin.  Generated from configure.ac by autoheader.  */\r
++\r
++/* Define to 1 if you have the `clock_gettime' function. */\r
++#define HAVE_CLOCK_GETTIME 1\r
++\r
++/* Define if you have compound literals. */\r
++#define HAVE_COMPOUND_LITERALS 1\r
++\r
++/* Define to 1 if you have the declaration of `tzname', and to 0 if you don't.\r
++   */\r
++/* #undef HAVE_DECL_TZNAME */\r
++\r
++/* Define to 1 if you have the `nanotime' function. */\r
++/* #undef HAVE_NANOTIME */\r
++\r
++/* Define to 1 if `tm_zone' is a member of `struct tm'. */\r
++#define HAVE_STRUCT_TM_TM_ZONE 1\r
++\r
++/* Define if struct tm has the tm_gmtoff member. */\r
++#define HAVE_TM_GMTOFF 1\r
++\r
++/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use\r
++   `HAVE_STRUCT_TM_TM_ZONE' instead. */\r
++#define HAVE_TM_ZONE 1\r
++\r
++/* Define to 1 if you don't have `tm_zone' but do have the external array\r
++   `tzname'. */\r
++/* #undef HAVE_TZNAME */\r
++\r
++/* Define to 1 if you have the `tzset' function. */\r
++#define HAVE_TZSET 1\r
++\r
++\r
++/* Define as a marker that can be attached to declarations that might not\r
++    be used.  This helps to reduce warnings, such as from\r
++    GCC -Wunused-parameter.  */\r
++#if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)\r
++# define _GL_UNUSED __attribute__ ((__unused__))\r
++#else\r
++# define _GL_UNUSED\r
++#endif\r
++/* The name _UNUSED_PARAMETER_ is an earlier spelling, although the name\r
++   is a misnomer outside of parameter lists.  */\r
++#define _UNUSED_PARAMETER_ _GL_UNUSED\r
+diff --git a/lib/getdate.c b/lib/getdate.c\r
+index 5b20eeb..57f33e9 100644\r
+--- a/lib/getdate.c\r
++++ b/lib/getdate.c\r
+@@ -68,7 +68,7 @@\r
+ /* Copy the first part of user declarations.  */\r
\r
+ /* Line 189 of yacc.c  */\r
+-#line 1 "getdate.y"\r
++#line 1 "lib/getdate.y"\r
\r
+ /* Parse a string into an internal time stamp.\r
\r
+@@ -102,6 +102,8 @@\r
+ /* FIXME: Check for arithmetic overflow in all cases, not just\r
+    some of them.  */\r
\r
++#include "notmuch-private.h"  /* For xmalloc() */\r
++\r
+ #include <config.h>\r
\r
+ #include "getdate.h"\r
+@@ -137,9 +139,6 @@\r
+ #include <stdlib.h>\r
+ #include <string.h>\r
\r
+-#include "xalloc.h"\r
+-\r
+-\r
+ /* ISDIGIT differs from isdigit, as follows:\r
+    - Its arg may be any int or unsigned int; it need not be an unsigned char\r
+      or EOF.\r
+@@ -344,7 +343,7 @@ set_hhmmss (parser_control *pc, long int hour, long int minutes,\r
\r
\r
+ /* Line 189 of yacc.c  */\r
+-#line 348 "getdate.c"\r
++#line 347 "lib/getdate.c"\r
\r
+ /* Enabling traces.  */\r
+ #ifndef YYDEBUG\r
+@@ -423,7 +422,7 @@ typedef union YYSTYPE\r
+ {\r
\r
+ /* Line 214 of yacc.c  */\r
+-#line 285 "getdate.y"\r
++#line 284 "lib/getdate.y"\r
\r
+   long int intval;\r
+   textint textintval;\r
+@@ -433,7 +432,7 @@ typedef union YYSTYPE\r
\r
\r
+ /* Line 214 of yacc.c  */\r
+-#line 437 "getdate.c"\r
++#line 436 "lib/getdate.c"\r
+ } YYSTYPE;\r
+ # define YYSTYPE_IS_TRIVIAL 1\r
+ # define yystype YYSTYPE /* obsolescent; will be withdrawn */\r
+@@ -445,7 +444,7 @@ typedef union YYSTYPE\r
\r
\r
+ /* Line 264 of yacc.c  */\r
+-#line 449 "getdate.c"\r
++#line 448 "lib/getdate.c"\r
\r
+ #ifdef short\r
+ # undef short\r
+@@ -759,15 +758,15 @@ static const yytype_int8 yyrhs[] =\r
+ /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */\r
+ static const yytype_uint16 yyrline[] =\r
+ {\r
+-       0,   311,   311,   312,   316,   323,   325,   329,   331,   333,\r
+-     335,   337,   339,   340,   341,   345,   350,   355,   362,   367,\r
+-     377,   382,   390,   392,   395,   397,   399,   404,   409,   414,\r
+-     419,   427,   432,   452,   459,   467,   475,   480,   486,   491,\r
+-     500,   502,   504,   509,   511,   513,   515,   517,   519,   521,\r
+-     523,   525,   527,   529,   531,   533,   535,   537,   539,   541,\r
+-     543,   545,   547,   549,   553,   555,   557,   559,   561,   563,\r
+-     568,   572,   572,   575,   576,   581,   582,   587,   592,   603,\r
+-     604,   610,   611\r
++       0,   310,   310,   311,   315,   322,   324,   328,   330,   332,\r
++     334,   336,   338,   339,   340,   344,   349,   354,   361,   366,\r
++     376,   381,   389,   391,   394,   396,   398,   403,   408,   413,\r
++     418,   426,   431,   451,   458,   466,   474,   479,   485,   490,\r
++     499,   501,   503,   508,   510,   512,   514,   516,   518,   520,\r
++     522,   524,   526,   528,   530,   532,   534,   536,   538,   540,\r
++     542,   544,   546,   548,   552,   554,   556,   558,   560,   562,\r
++     567,   571,   571,   574,   575,   580,   581,   586,   591,   602,\r
++     603,   609,   610\r
+ };\r
+ #endif\r
\r
+@@ -1742,7 +1741,7 @@ yyreduce:\r
+         case 4:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 317 "getdate.y"\r
++#line 316 "lib/getdate.y"\r
+     {\r
+         pc->seconds = (yyvsp[(2) - (2)].timespec);\r
+         pc->timespec_seen = true;\r
+@@ -1752,42 +1751,42 @@ yyreduce:\r
+   case 7:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 330 "getdate.y"\r
++#line 329 "lib/getdate.y"\r
+     { pc->times_seen++; }\r
+     break;\r
\r
+   case 8:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 332 "getdate.y"\r
++#line 331 "lib/getdate.y"\r
+     { pc->local_zones_seen++; }\r
+     break;\r
\r
+   case 9:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 334 "getdate.y"\r
++#line 333 "lib/getdate.y"\r
+     { pc->zones_seen++; }\r
+     break;\r
\r
+   case 10:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 336 "getdate.y"\r
++#line 335 "lib/getdate.y"\r
+     { pc->dates_seen++; }\r
+     break;\r
\r
+   case 11:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 338 "getdate.y"\r
++#line 337 "lib/getdate.y"\r
+     { pc->days_seen++; }\r
+     break;\r
\r
+   case 15:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 346 "getdate.y"\r
++#line 345 "lib/getdate.y"\r
+     {\r
+         set_hhmmss (pc, (yyvsp[(1) - (2)].textintval).value, 0, 0, 0);\r
+         pc->meridian = (yyvsp[(2) - (2)].intval);\r
+@@ -1797,7 +1796,7 @@ yyreduce:\r
+   case 16:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 351 "getdate.y"\r
++#line 350 "lib/getdate.y"\r
+     {\r
+         set_hhmmss (pc, (yyvsp[(1) - (4)].textintval).value, (yyvsp[(3) - (4)].textintval).value, 0, 0);\r
+         pc->meridian = (yyvsp[(4) - (4)].intval);\r
+@@ -1807,7 +1806,7 @@ yyreduce:\r
+   case 17:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 356 "getdate.y"\r
++#line 355 "lib/getdate.y"\r
+     {\r
+         set_hhmmss (pc, (yyvsp[(1) - (5)].textintval).value, (yyvsp[(3) - (5)].textintval).value, 0, 0);\r
+         pc->meridian = MER24;\r
+@@ -1819,7 +1818,7 @@ yyreduce:\r
+   case 18:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 363 "getdate.y"\r
++#line 362 "lib/getdate.y"\r
+     {\r
+         set_hhmmss (pc, (yyvsp[(1) - (6)].textintval).value, (yyvsp[(3) - (6)].textintval).value, (yyvsp[(5) - (6)].timespec).tv_sec, (yyvsp[(5) - (6)].timespec).tv_nsec);\r
+         pc->meridian = (yyvsp[(6) - (6)].intval);\r
+@@ -1829,7 +1828,7 @@ yyreduce:\r
+   case 19:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 368 "getdate.y"\r
++#line 367 "lib/getdate.y"\r
+     {\r
+         set_hhmmss (pc, (yyvsp[(1) - (7)].textintval).value, (yyvsp[(3) - (7)].textintval).value, (yyvsp[(5) - (7)].timespec).tv_sec, (yyvsp[(5) - (7)].timespec).tv_nsec);\r
+         pc->meridian = MER24;\r
+@@ -1841,7 +1840,7 @@ yyreduce:\r
+   case 20:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 378 "getdate.y"\r
++#line 377 "lib/getdate.y"\r
+     {\r
+         pc->local_isdst = (yyvsp[(1) - (1)].intval);\r
+         pc->dsts_seen += (0 < (yyvsp[(1) - (1)].intval));\r
+@@ -1851,7 +1850,7 @@ yyreduce:\r
+   case 21:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 383 "getdate.y"\r
++#line 382 "lib/getdate.y"\r
+     {\r
+         pc->local_isdst = 1;\r
+         pc->dsts_seen += (0 < (yyvsp[(1) - (2)].intval)) + 1;\r
+@@ -1861,14 +1860,14 @@ yyreduce:\r
+   case 22:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 391 "getdate.y"\r
++#line 390 "lib/getdate.y"\r
+     { pc->time_zone = (yyvsp[(1) - (1)].intval); }\r
+     break;\r
\r
+   case 23:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 393 "getdate.y"\r
++#line 392 "lib/getdate.y"\r
+     { pc->time_zone = (yyvsp[(1) - (2)].intval);\r
+         apply_relative_time (pc, (yyvsp[(2) - (2)].rel), 1); }\r
+     break;\r
+@@ -1876,28 +1875,28 @@ yyreduce:\r
+   case 24:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 396 "getdate.y"\r
++#line 395 "lib/getdate.y"\r
+     { pc->time_zone = (yyvsp[(1) - (3)].intval) + time_zone_hhmm (pc, (yyvsp[(2) - (3)].textintval), (yyvsp[(3) - (3)].intval)); }\r
+     break;\r
\r
+   case 25:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 398 "getdate.y"\r
++#line 397 "lib/getdate.y"\r
+     { pc->time_zone = (yyvsp[(1) - (1)].intval) + 60; }\r
+     break;\r
\r
+   case 26:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 400 "getdate.y"\r
++#line 399 "lib/getdate.y"\r
+     { pc->time_zone = (yyvsp[(1) - (2)].intval) + 60; }\r
+     break;\r
\r
+   case 27:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 405 "getdate.y"\r
++#line 404 "lib/getdate.y"\r
+     {\r
+         pc->day_ordinal = 0;\r
+         pc->day_number = (yyvsp[(1) - (1)].intval);\r
+@@ -1907,7 +1906,7 @@ yyreduce:\r
+   case 28:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 410 "getdate.y"\r
++#line 409 "lib/getdate.y"\r
+     {\r
+         pc->day_ordinal = 0;\r
+         pc->day_number = (yyvsp[(1) - (2)].intval);\r
+@@ -1917,7 +1916,7 @@ yyreduce:\r
+   case 29:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 415 "getdate.y"\r
++#line 414 "lib/getdate.y"\r
+     {\r
+         pc->day_ordinal = (yyvsp[(1) - (2)].intval);\r
+         pc->day_number = (yyvsp[(2) - (2)].intval);\r
+@@ -1927,7 +1926,7 @@ yyreduce:\r
+   case 30:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 420 "getdate.y"\r
++#line 419 "lib/getdate.y"\r
+     {\r
+         pc->day_ordinal = (yyvsp[(1) - (2)].textintval).value;\r
+         pc->day_number = (yyvsp[(2) - (2)].intval);\r
+@@ -1937,7 +1936,7 @@ yyreduce:\r
+   case 31:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 428 "getdate.y"\r
++#line 427 "lib/getdate.y"\r
+     {\r
+         pc->month = (yyvsp[(1) - (3)].textintval).value;\r
+         pc->day = (yyvsp[(3) - (3)].textintval).value;\r
+@@ -1947,7 +1946,7 @@ yyreduce:\r
+   case 32:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 433 "getdate.y"\r
++#line 432 "lib/getdate.y"\r
+     {\r
+         /* Interpret as YYYY/MM/DD if the first value has 4 or more digits,\r
+            otherwise as MM/DD/YY.\r
+@@ -1972,7 +1971,7 @@ yyreduce:\r
+   case 33:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 453 "getdate.y"\r
++#line 452 "lib/getdate.y"\r
+     {\r
+         /* ISO 8601 format.  YYYY-MM-DD.  */\r
+         pc->year = (yyvsp[(1) - (3)].textintval);\r
+@@ -1984,7 +1983,7 @@ yyreduce:\r
+   case 34:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 460 "getdate.y"\r
++#line 459 "lib/getdate.y"\r
+     {\r
+         /* e.g. 17-JUN-1992.  */\r
+         pc->day = (yyvsp[(1) - (3)].textintval).value;\r
+@@ -1997,7 +1996,7 @@ yyreduce:\r
+   case 35:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 468 "getdate.y"\r
++#line 467 "lib/getdate.y"\r
+     {\r
+         /* e.g. JUN-17-1992.  */\r
+         pc->month = (yyvsp[(1) - (3)].intval);\r
+@@ -2010,7 +2009,7 @@ yyreduce:\r
+   case 36:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 476 "getdate.y"\r
++#line 475 "lib/getdate.y"\r
+     {\r
+         pc->month = (yyvsp[(1) - (2)].intval);\r
+         pc->day = (yyvsp[(2) - (2)].textintval).value;\r
+@@ -2020,7 +2019,7 @@ yyreduce:\r
+   case 37:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 481 "getdate.y"\r
++#line 480 "lib/getdate.y"\r
+     {\r
+         pc->month = (yyvsp[(1) - (4)].intval);\r
+         pc->day = (yyvsp[(2) - (4)].textintval).value;\r
+@@ -2031,7 +2030,7 @@ yyreduce:\r
+   case 38:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 487 "getdate.y"\r
++#line 486 "lib/getdate.y"\r
+     {\r
+         pc->day = (yyvsp[(1) - (2)].textintval).value;\r
+         pc->month = (yyvsp[(2) - (2)].intval);\r
+@@ -2041,7 +2040,7 @@ yyreduce:\r
+   case 39:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 492 "getdate.y"\r
++#line 491 "lib/getdate.y"\r
+     {\r
+         pc->day = (yyvsp[(1) - (3)].textintval).value;\r
+         pc->month = (yyvsp[(2) - (3)].intval);\r
+@@ -2052,238 +2051,238 @@ yyreduce:\r
+   case 40:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 501 "getdate.y"\r
++#line 500 "lib/getdate.y"\r
+     { apply_relative_time (pc, (yyvsp[(1) - (2)].rel), -1); }\r
+     break;\r
\r
+   case 41:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 503 "getdate.y"\r
++#line 502 "lib/getdate.y"\r
+     { apply_relative_time (pc, (yyvsp[(1) - (1)].rel), 1); }\r
+     break;\r
\r
+   case 42:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 505 "getdate.y"\r
++#line 504 "lib/getdate.y"\r
+     { apply_relative_time (pc, (yyvsp[(1) - (1)].rel), 1); }\r
+     break;\r
\r
+   case 43:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 510 "getdate.y"\r
++#line 509 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = (yyvsp[(1) - (2)].intval); }\r
+     break;\r
\r
+   case 44:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 512 "getdate.y"\r
++#line 511 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = (yyvsp[(1) - (2)].textintval).value; }\r
+     break;\r
\r
+   case 45:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 514 "getdate.y"\r
++#line 513 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = 1; }\r
+     break;\r
\r
+   case 46:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 516 "getdate.y"\r
++#line 515 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = (yyvsp[(1) - (2)].intval); }\r
+     break;\r
\r
+   case 47:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 518 "getdate.y"\r
++#line 517 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = (yyvsp[(1) - (2)].textintval).value; }\r
+     break;\r
\r
+   case 48:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 520 "getdate.y"\r
++#line 519 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = 1; }\r
+     break;\r
\r
+   case 49:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 522 "getdate.y"\r
++#line 521 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (2)].intval) * (yyvsp[(2) - (2)].intval); }\r
+     break;\r
\r
+   case 50:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 524 "getdate.y"\r
++#line 523 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); }\r
+     break;\r
\r
+   case 51:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 526 "getdate.y"\r
++#line 525 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (1)].intval); }\r
+     break;\r
\r
+   case 52:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 528 "getdate.y"\r
++#line 527 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = (yyvsp[(1) - (2)].intval); }\r
+     break;\r
\r
+   case 53:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 530 "getdate.y"\r
++#line 529 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = (yyvsp[(1) - (2)].textintval).value; }\r
+     break;\r
\r
+   case 54:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 532 "getdate.y"\r
++#line 531 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = 1; }\r
+     break;\r
\r
+   case 55:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 534 "getdate.y"\r
++#line 533 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = (yyvsp[(1) - (2)].intval); }\r
+     break;\r
\r
+   case 56:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 536 "getdate.y"\r
++#line 535 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = (yyvsp[(1) - (2)].textintval).value; }\r
+     break;\r
\r
+   case 57:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 538 "getdate.y"\r
++#line 537 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = 1; }\r
+     break;\r
\r
+   case 58:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 540 "getdate.y"\r
++#line 539 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].intval); }\r
+     break;\r
\r
+   case 59:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 542 "getdate.y"\r
++#line 541 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].textintval).value; }\r
+     break;\r
\r
+   case 60:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 544 "getdate.y"\r
++#line 543 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].timespec).tv_sec; (yyval.rel).ns = (yyvsp[(1) - (2)].timespec).tv_nsec; }\r
+     break;\r
\r
+   case 61:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 546 "getdate.y"\r
++#line 545 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].timespec).tv_sec; (yyval.rel).ns = (yyvsp[(1) - (2)].timespec).tv_nsec; }\r
+     break;\r
\r
+   case 62:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 548 "getdate.y"\r
++#line 547 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = 1; }\r
+     break;\r
\r
+   case 64:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 554 "getdate.y"\r
++#line 553 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).year = (yyvsp[(1) - (2)].textintval).value; }\r
+     break;\r
\r
+   case 65:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 556 "getdate.y"\r
++#line 555 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).month = (yyvsp[(1) - (2)].textintval).value; }\r
+     break;\r
\r
+   case 66:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 558 "getdate.y"\r
++#line 557 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (2)].textintval).value * (yyvsp[(2) - (2)].intval); }\r
+     break;\r
\r
+   case 67:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 560 "getdate.y"\r
++#line 559 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).hour = (yyvsp[(1) - (2)].textintval).value; }\r
+     break;\r
\r
+   case 68:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 562 "getdate.y"\r
++#line 561 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).minutes = (yyvsp[(1) - (2)].textintval).value; }\r
+     break;\r
\r
+   case 69:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 564 "getdate.y"\r
++#line 563 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).seconds = (yyvsp[(1) - (2)].textintval).value; }\r
+     break;\r
\r
+   case 70:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 569 "getdate.y"\r
++#line 568 "lib/getdate.y"\r
+     { (yyval.rel) = RELATIVE_TIME_0; (yyval.rel).day = (yyvsp[(1) - (1)].intval); }\r
+     break;\r
\r
+   case 74:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 577 "getdate.y"\r
++#line 576 "lib/getdate.y"\r
+     { (yyval.timespec).tv_sec = (yyvsp[(1) - (1)].textintval).value; (yyval.timespec).tv_nsec = 0; }\r
+     break;\r
\r
+   case 76:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 583 "getdate.y"\r
++#line 582 "lib/getdate.y"\r
+     { (yyval.timespec).tv_sec = (yyvsp[(1) - (1)].textintval).value; (yyval.timespec).tv_nsec = 0; }\r
+     break;\r
\r
+   case 77:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 588 "getdate.y"\r
++#line 587 "lib/getdate.y"\r
+     { digits_to_date_time (pc, (yyvsp[(1) - (1)].textintval)); }\r
+     break;\r
\r
+   case 78:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 593 "getdate.y"\r
++#line 592 "lib/getdate.y"\r
+     {\r
+         /* Hybrid all-digit and relative offset, so that we accept e.g.,\r
+            "YYYYMMDD +N days" as well as "YYYYMMDD N days".  */\r
+@@ -2295,35 +2294,35 @@ yyreduce:\r
+   case 79:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 603 "getdate.y"\r
++#line 602 "lib/getdate.y"\r
+     { (yyval.intval) = -1; }\r
+     break;\r
\r
+   case 80:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 605 "getdate.y"\r
++#line 604 "lib/getdate.y"\r
+     { (yyval.intval) = (yyvsp[(2) - (2)].textintval).value; }\r
+     break;\r
\r
+   case 81:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 610 "getdate.y"\r
++#line 609 "lib/getdate.y"\r
+     { (yyval.intval) = MER24; }\r
+     break;\r
\r
+   case 82:\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 612 "getdate.y"\r
++#line 611 "lib/getdate.y"\r
+     { (yyval.intval) = (yyvsp[(1) - (1)].intval); }\r
+     break;\r
\r
\r
\r
+ /* Line 1455 of yacc.c  */\r
+-#line 2327 "getdate.c"\r
++#line 2326 "lib/getdate.c"\r
+       default: break;\r
+     }\r
+   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);\r
+@@ -2535,7 +2534,7 @@ yyreturn:\r
\r
\r
+ /* Line 1675 of yacc.c  */\r
+-#line 615 "getdate.y"\r
++#line 614 "lib/getdate.y"\r
\r
\r
+ static table const meridian_table[] =\r
+@@ -3104,6 +3103,16 @@ mktime_ok (struct tm const *tm0, struct tm const *tm1, time_t t)\r
+    Use heap allocation if TZ's length exceeds this.  */\r
+ enum { TZBUFSIZE = 100 };\r
\r
++/* Clone an object P of size S, with error checking.  There's no need\r
++   for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any\r
++   need for an arithmetic overflow check.  */\r
++\r
++static void *\r
++xmemdup (void const *p, size_t s)\r
++{\r
++  return memcpy (xmalloc (s), p, s);\r
++}\r
++\r
+ /* Return a copy of TZ, stored in TZBUF if it fits, and heap-allocated\r
+    otherwise.  */\r
+ static char *\r
+diff --git a/lib/getdate.h b/lib/getdate.h\r
+index 22cc2c0..ad1283c 100644\r
+--- a/lib/getdate.h\r
++++ b/lib/getdate.h\r
+@@ -19,4 +19,13 @@\r
+ #include <stdbool.h>\r
+ #include <time.h>\r
\r
++#ifdef __cplusplus\r
++extern "C" {\r
++#endif\r
++\r
+ bool get_date (struct timespec *, char const *, struct timespec const *);\r
++\r
++#ifdef __cplusplus\r
++}\r
++#endif\r
++\r
+diff --git a/lib/getdate.y b/lib/getdate.y\r
+index 445865b..d423f5b 100644\r
+--- a/lib/getdate.y\r
++++ b/lib/getdate.y\r
+@@ -31,6 +31,8 @@\r
+ /* FIXME: Check for arithmetic overflow in all cases, not just\r
+    some of them.  */\r
\r
++#include "notmuch-private.h"  /* For xmalloc() */\r
++\r
+ #include <config.h>\r
\r
+ #include "getdate.h"\r
+@@ -66,9 +68,6 @@\r
+ #include <stdlib.h>\r
+ #include <string.h>\r
\r
+-#include "xalloc.h"\r
+-\r
+-\r
+ /* ISDIGIT differs from isdigit, as follows:\r
+    - Its arg may be any int or unsigned int; it need not be an unsigned char\r
+      or EOF.\r
+@@ -1180,6 +1179,16 @@ mktime_ok (struct tm const *tm0, struct tm const *tm1, time_t t)\r
+    Use heap allocation if TZ's length exceeds this.  */\r
+ enum { TZBUFSIZE = 100 };\r
\r
++/* Clone an object P of size S, with error checking.  There's no need\r
++   for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any\r
++   need for an arithmetic overflow check.  */\r
++\r
++static void *\r
++xmemdup (void const *p, size_t s)\r
++{\r
++  return memcpy (xmalloc (s), p, s);\r
++}\r
++\r
+ /* Return a copy of TZ, stored in TZBUF if it fits, and heap-allocated\r
+    otherwise.  */\r
+ static char *\r
+-- \r
+1.7.1\r
+\r