From ef5d91059ec3b50e41a3639c549160d92e8513c4 Mon Sep 17 00:00:00 2001 From: "William M. Brack" Date: Thu, 30 Sep 2004 18:33:30 +0000 Subject: [PATCH] fixed problem with negative periods (bug 154021) changed expected output, * libexslt/date.c: fixed problem with negative periods (bug 154021) * tests/exslt/date/sum.2.out: changed expected output, now agrees with comments in sum.2.xml test data file --- ChangeLog | 7 ++++ libexslt/date.c | 90 +++++++++++++++++++++++++++++----------------- libxslt/xsltwin32config.h | 2 +- tests/exslt/date/sum.2.out | 4 +-- 4 files changed, 67 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index b3a906d..3b7c0db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Thu Sep 30 11:28:03 PDT 2004 William Brack + + * libexslt/date.c: fixed problem with negative periods + (bug 154021) + * tests/exslt/date/sum.2.out: changed expected output, now + agrees with comments in sum.2.xml test data file + Thu Sep 30 08:19:28 CEST 2004 Daniel Veillard * libxslt/templates.c: patch from Mark Vakoc about an incorrect diff --git a/libexslt/date.c b/libexslt/date.c index 672f1b4..29cbdfe 100644 --- a/libexslt/date.c +++ b/libexslt/date.c @@ -1651,27 +1651,22 @@ _exsltDateDifference (exsltDateValPtr x, exsltDateValPtr y, int flag) } /** - * _exsltDateAddDuration: - * @x: an #exsltDateValPtr of type #XS_DURATION - * @y: an #exsltDateValPtr of type #XS_DURATION + * _exsltDateAddDurCalc + * @ret: an exsltDateValPtr for the return value: + * @x: an exsltDateValPtr for the first operand + * @y: an exsltDateValPtr for the second operand * - * Compute a new duration from @x and @y. + * Add two durations, catering for possible negative values. + * The sum is placed in @ret. * - * Returns date/time pointer or NULL. + * Returns 1 for success, 0 if error detected. */ -static exsltDateValPtr -_exsltDateAddDuration (exsltDateValPtr x, exsltDateValPtr y) +static int +_exsltDateAddDurCalc (exsltDateValPtr ret, exsltDateValPtr x, + exsltDateValPtr y) { - exsltDateValPtr ret; long carry; - if ((x == NULL) || (y == NULL)) - return NULL; - - ret = exsltDateCreateDate(XS_DURATION); - if (ret == NULL) - return NULL; - /* months */ ret->value.dur.mon = x->value.dur.mon + y->value.dur.mon; @@ -1680,6 +1675,16 @@ _exsltDateAddDuration (exsltDateValPtr x, exsltDateValPtr y) carry = (long)FQUOTIENT(ret->value.dur.sec, SECS_PER_DAY); if (ret->value.dur.sec != 0.0) { ret->value.dur.sec = MODULO(ret->value.dur.sec, SECS_PER_DAY); + /* + * Our function MODULO always gives us a positive value, so + * if we end up with a "-ve" carry we need to adjust it + * appropriately (bug 154021) + */ + if ((carry < 0) && (ret->value.dur.sec != 0)) { + /* change seconds to equiv negative modulus */ + ret->value.dur.sec = ret->value.dur.sec - SECS_PER_DAY; + carry++; + } } /* days */ @@ -1693,11 +1698,37 @@ _exsltDateAddDuration (exsltDateValPtr x, exsltDateValPtr y) (ret->value.dur.mon < 0)) || (((ret->value.dur.day < 0) || (ret->value.dur.sec < 0)) && (ret->value.dur.mon > 0))) { - exsltDateFreeDate(ret); - return NULL; + return 0; } + return 1; +} - return ret; +/** + * _exsltDateAddDuration: + * @x: an #exsltDateValPtr of type #XS_DURATION + * @y: an #exsltDateValPtr of type #XS_DURATION + * + * Compute a new duration from @x and @y. + * + * Returns date/time pointer or NULL. + */ +static exsltDateValPtr +_exsltDateAddDuration (exsltDateValPtr x, exsltDateValPtr y) +{ + exsltDateValPtr ret; + + if ((x == NULL) || (y == NULL)) + return NULL; + + ret = exsltDateCreateDate(XS_DURATION); + if (ret == NULL) + return NULL; + + if (_exsltDateAddDurCalc(ret, x, y)) + return ret; + + exsltDateFreeDate(ret); + return NULL; } /**************************************************************** @@ -2729,7 +2760,6 @@ exsltDateSumFunction (xmlXPathParserContextPtr ctxt, int nargs) xmlChar *tmp; exsltDateValPtr x, total; xmlChar *ret; - long carry; int i; if (nargs != 1) { @@ -2762,7 +2792,7 @@ exsltDateSumFunction (xmlXPathParserContextPtr ctxt, int nargs) } for (i = 0; i < ns->nodeNr; i++) { - + int result; tmp = xmlXPathCastNodeToString (ns->nodeTab[i]); if (tmp == NULL) { xmlXPathFreeNodeSet (ns); @@ -2779,22 +2809,16 @@ exsltDateSumFunction (xmlXPathParserContextPtr ctxt, int nargs) return; } - /* months */ - total->value.dur.mon += x->value.dur.mon; - - /* seconds */ - total->value.dur.sec += x->value.dur.sec; - carry = (long) FQUOTIENT (total->value.dur.sec, SECS_PER_DAY); - if (total->value.dur.sec != 0.0) { - total->value.dur.sec = - MODULO (total->value.dur.sec, SECS_PER_DAY); - } - - /* days */ - total->value.dur.day += x->value.dur.day + carry; + result = _exsltDateAddDurCalc(total, total, x); exsltDateFreeDate (x); xmlFree (tmp); + if (!result) { + exsltDateFreeDate (total); + xmlXPathFreeNodeSet (ns); + xmlXPathReturnEmptyString (ctxt); + return; + } } ret = exsltDateFormatDuration (&(total->value.dur)); diff --git a/libxslt/xsltwin32config.h b/libxslt/xsltwin32config.h index 09a424c..c468a9d 100644 --- a/libxslt/xsltwin32config.h +++ b/libxslt/xsltwin32config.h @@ -44,7 +44,7 @@ extern "C" { * * extra version information, used to show a CVS compilation */ -#define LIBXML_VERSION_EXTRA "-CVS951" +#define LIBXML_VERSION_EXTRA "-CVS954" /** * WITH_XSLT_DEBUG: diff --git a/tests/exslt/date/sum.2.out b/tests/exslt/date/sum.2.out index 27f7535..8c9cdda 100644 --- a/tests/exslt/date/sum.2.out +++ b/tests/exslt/date/sum.2.out @@ -2,9 +2,9 @@ sum : result : sum : P1M + -P1D -result : -P1M1D +result : sum : P1M + -P1D + P1D -result : P1M +result : sum : P1M + P1D + -P1D result : P1M sum : -- 2.7.4