--- /dev/null
+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