1
0
mirror of https://git.savannah.gnu.org/git/gnulib.git synced 2025-08-08 17:22:05 +03:00

parse-datetime: improve debug implementation

Follow-up to commit 12ad79069 ("add optional debug printing").
Improve parse-datetime's debug implementation: remove macros,
replace global debug flag variable with a function parameter,
use nstrftime for formatting.
See: https://lists.gnu.org/archive/html/bug-gnulib/2016-08/msg00021.html

* lib/parse-datetime.h: (parse_datetime_debug): Remove global extern
declaration.
(parse_datetime2): New function, accepts 'flags' parameter, supporting
debug flag. Existing interface 'parse_datetime' left unmodified.
* lib/parse-datetime.c: (parse_datetime_debug): Remove global variable.
(struct parser_control): add 'parse_datetime_debug' member variable.
(parse_datetime): Call new function 'parse_datetime2' without debug.
(parse_datetime2): Adapted from previous 'parse_datetime', initialize
pc.parse_datetime_debug variable as needed.
(to_year): Accept new flags parameter, instead of using global variable.
(debug_print_current_time,debug_print_relative_time,debug_mktime_not_ok):
use struct 'debug' variable instead of global variable.
(DEBUG,DEBUG_PRINT_CURRENT_TIME,DEBUG_PRINT_RELATIVE_TIME,
DEBUG_MKTIME_NOT_OK,PROGRESS,PROGRESS0): Remove macros. Call
correspnding functions directly instead of using macros.
* modules/parse-datetime: Add gnulib's strftime module.
This commit is contained in:
Assaf Gordon
2016-08-14 21:29:50 -04:00
committed by Pádraig Brady
parent 6e2966216e
commit 5d36768ce2
4 changed files with 204 additions and 160 deletions

View File

@@ -1,3 +1,27 @@
2016-08-19 Assaf Gordon <assafgordon@gmail.com>
parse-datetime: improve debug implementation
Follow-up to commit 12ad79069 ("add optional debug printing").
Improve parse-datetime's debug implementation: remove macros,
replace global debug flag variable with a function parameter,
use nstrftime for formatting.
See: https://lists.gnu.org/archive/html/bug-gnulib/2016-08/msg00021.html
* lib/parse-datetime.h: (parse_datetime_debug): Remove global extern.
(parse_datetime2): New function, accepts 'flags' parameter, supporting
debug flag. Existing interface 'parse_datetime' left unmodified.
* lib/parse-datetime.c: (parse_datetime_debug): Remove global variable.
(struct parser_control): add 'parse_datetime_debug' member variable.
(parse_datetime): Call new function 'parse_datetime2' without debug.
(parse_datetime2): Adapted from previous 'parse_datetime', initialize
pc.parse_datetime_debug variable as needed.
(to_year): Accept new flags parameter, instead of using global variable.
(debug_print_current_time,debug_print_relative_time,debug_mktime_not_ok):
use struct 'debug' variable instead of global variable.
(DEBUG,DEBUG_PRINT_CURRENT_TIME,DEBUG_PRINT_RELATIVE_TIME,
DEBUG_MKTIME_NOT_OK,PROGRESS,PROGRESS0): Remove macros. Call
correspnding functions directly instead of using macros.
* modules/parse-datetime: Add gnulib's strftime module.
2016-08-19 Daniel Richard G. <skunk@iSKUNK.ORG> 2016-08-19 Daniel Richard G. <skunk@iSKUNK.ORG>
c-strcase-tests: port to EBCDIC c-strcase-tests: port to EBCDIC

View File

@@ -19,6 +19,11 @@
#include <stdbool.h> #include <stdbool.h>
#include <time.h> #include <time.h>
extern bool parse_datetime_debug;
bool parse_datetime (struct timespec *, char const *, struct timespec const *); bool parse_datetime (struct timespec *, char const *, struct timespec const *);
/* parse_datetime2 flag: if set, print debug/progress information to STDERR */
#define PARSE_DATETIME_DEBUG 1
/* same as above, supporting additional flags */
bool parse_datetime2 (struct timespec *, char const *, struct timespec const *,
unsigned int flags);

View File

@@ -37,6 +37,7 @@
#include "intprops.h" #include "intprops.h"
#include "timespec.h" #include "timespec.h"
#include "verify.h" #include "verify.h"
#include "strftime.h"
/* There's no need to extend the stack, so there's no need to involve /* There's no need to extend the stack, so there's no need to involve
alloca. */ alloca. */
@@ -124,50 +125,6 @@ typedef time_t long_time_t;
errors that the cast doesn't. */ errors that the cast doesn't. */
static unsigned char to_uchar (char ch) { return ch; } static unsigned char to_uchar (char ch) { return ch; }
/* Enable diagnostic debug output to STDERR */
bool parse_datetime_debug = false;
/* Debug message without parameters */
#define DEBUG0(msg) \
do { \
if (parse_datetime_debug) \
dbg_printf (msg); \
} while (0)
/* Debug message with printf-style parameters */
#define DEBUG(x,...) \
do { \
if (parse_datetime_debug) \
dbg_printf (x,__VA_ARGS__); \
} while (0)
/* Progress messages treated the same as debug messages */
#define PROGRESS DEBUG
#define PROGRESS0 DEBUG0
/* Print the date/time of the parser_control struct */
#define DEBUG_PRINT_CURRENT_TIME(item,pc) \
do { \
if (parse_datetime_debug) \
debug_print_current_time (item, pc); \
} while (0)
/* Print the relative date/time of the parser control struct */
#define DEBUG_PRINT_RELATIVE_TIME(item,pc) \
do { \
if (parse_datetime_debug) \
debug_print_rel_time (item, pc); \
} while (0)
/* if 'mktime_ok' failed, print informative message with possible reasons */
#define DEBUG_MKTIME_NOT_OK(tm0,tm1,pc,zones_seen) \
do { \
if (parse_datetime_debug) \
debug_mktime_not_ok (tm0, tm1, pc, zones_seen); \
} while (0)
static void static void
dbg_printf (const char *msg,...) dbg_printf (const char *msg,...)
{ {
@@ -273,6 +230,9 @@ typedef struct
size_t times_seen; size_t times_seen;
size_t zones_seen; size_t zones_seen;
/* if true, print debugging output to stderr */
bool parse_datetime_debug;
/* which of the 'seen' parts has been printed when debugging */ /* which of the 'seen' parts has been printed when debugging */
size_t debug_dates_seen; size_t debug_dates_seen;
size_t debug_days_seen; size_t debug_days_seen;
@@ -438,7 +398,12 @@ debug_print_current_time (const char* item, parser_control *pc)
{ {
char tmp[100] = {0}; char tmp[100] = {0};
int space = 0; /* if true, add space delimiter */ int space = 0; /* if true, add space delimiter */
DEBUG (_("parsed %s part: "), item); /* no newline, more items printed below */
if (!pc->parse_datetime_debug)
return;
/* no newline, more items printed below */
dbg_printf (_("parsed %s part: "), item);
if (pc->dates_seen != pc->debug_dates_seen) if (pc->dates_seen != pc->debug_dates_seen)
{ {
@@ -517,10 +482,15 @@ debug_print_current_time (const char* item, parser_control *pc)
/* debugging: print the current relative values. */ /* debugging: print the current relative values. */
static void static void
debug_print_rel_time (const char* item, const parser_control *pc) debug_print_relative_time (const char* item, const parser_control *pc)
{ {
int space = 0; /* if true, add space delimiter */ int space = 0; /* if true, add space delimiter */
DEBUG (_("parsed %s part: "), item); /* no newline, more items printed below */
if (!pc->parse_datetime_debug)
return;
/* no newline, more items printed below */
dbg_printf (_("parsed %s part: "), item);
if (pc->rel.year==0 && pc->rel.month==0 && pc->rel.day==0 if (pc->rel.year==0 && pc->rel.month==0 && pc->rel.day==0
&& pc->rel.hour==0 && pc->rel.minutes==00 && pc->rel.seconds == 0 && pc->rel.hour==0 && pc->rel.minutes==00 && pc->rel.seconds == 0
@@ -603,7 +573,7 @@ timespec:
{ {
pc->seconds = $2; pc->seconds = $2;
pc->timespec_seen = true; pc->timespec_seen = true;
DEBUG_PRINT_CURRENT_TIME (_("number of seconds"), pc); debug_print_current_time (_("number of seconds"), pc);
} }
; ;
@@ -616,44 +586,44 @@ item:
datetime datetime
{ {
pc->times_seen++; pc->dates_seen++; pc->times_seen++; pc->dates_seen++;
DEBUG_PRINT_CURRENT_TIME (_("datetime"), pc); debug_print_current_time (_("datetime"), pc);
} }
| time | time
{ {
pc->times_seen++; pc->times_seen++;
DEBUG_PRINT_CURRENT_TIME (_("time"), pc); debug_print_current_time (_("time"), pc);
} }
| local_zone | local_zone
{ {
pc->local_zones_seen++; pc->local_zones_seen++;
DEBUG_PRINT_CURRENT_TIME (_("local_zone"), pc); debug_print_current_time (_("local_zone"), pc);
} }
| zone | zone
{ {
pc->zones_seen++; pc->zones_seen++;
DEBUG_PRINT_CURRENT_TIME (_("zone"), pc); debug_print_current_time (_("zone"), pc);
} }
| date | date
{ {
pc->dates_seen++; pc->dates_seen++;
DEBUG_PRINT_CURRENT_TIME (_("date"), pc); debug_print_current_time (_("date"), pc);
} }
| day | day
{ {
pc->days_seen++; pc->days_seen++;
DEBUG_PRINT_CURRENT_TIME (_("day"), pc); debug_print_current_time (_("day"), pc);
} }
| rel | rel
{ {
DEBUG_PRINT_RELATIVE_TIME (_("relative"), pc); debug_print_relative_time (_("relative"), pc);
} }
| number | number
{ {
DEBUG_PRINT_RELATIVE_TIME (_("number"), pc); debug_print_relative_time (_("number"), pc);
} }
| hybrid | hybrid
{ {
DEBUG_PRINT_RELATIVE_TIME (_("hybrid"), pc); debug_print_relative_time (_("hybrid"), pc);
} }
; ;
@@ -789,7 +759,8 @@ date:
you want portability, use the ISO 8601 format. */ you want portability, use the ISO 8601 format. */
if (4 <= $1.digits) if (4 <= $1.digits)
{ {
DEBUG (_("warning: value %ld has %"PRIuMAX" digits. " \ if (pc->parse_datetime_debug)
dbg_printf (_("warning: value %ld has %"PRIuMAX" digits. " \
"Assuming YYYY/MM/DD\n"), $1.value, $1.digits); "Assuming YYYY/MM/DD\n"), $1.value, $1.digits);
pc->year = $1; pc->year = $1;
@@ -798,7 +769,8 @@ date:
} }
else else
{ {
DEBUG (_("warning: value %ld has less than 4 digits. " \ if (pc->parse_datetime_debug)
dbg_printf (_("warning: value %ld has less than 4 digits. " \
"Assuming MM/DD/YY[YY]\n"), $1.value); "Assuming MM/DD/YY[YY]\n"), $1.value);
pc->month = $1.value; pc->month = $1.value;
@@ -1204,7 +1176,7 @@ to_hour (long int hours, int meridian)
} }
static long int static long int
to_year (textint textyear) to_year (textint textyear, bool debug)
{ {
long int year = textyear.value; long int year = textyear.value;
@@ -1216,7 +1188,8 @@ to_year (textint textyear)
else if (textyear.digits == 2) else if (textyear.digits == 2)
{ {
year += year < 69 ? 2000 : 1900; year += year < 69 ? 2000 : 1900;
DEBUG (_("warning: adjusting year value %ld to %ld\n"), if (debug)
dbg_printf (_("warning: adjusting year value %ld to %ld\n"),
textyear.value, year); textyear.value, year);
} }
@@ -1484,7 +1457,8 @@ yylex (union YYSTYPE *lvalp, parser_control *pc)
tp = lookup_word (pc, buff); tp = lookup_word (pc, buff);
if (! tp) if (! tp)
{ {
DEBUG (_("error: unknown word '%s'\n"), buff); if (pc->parse_datetime_debug)
dbg_printf (_("error: unknown word '%s'\n"), buff);
return '?'; return '?';
} }
lvalp->intval = tp->value; lvalp->intval = tp->value;
@@ -1595,9 +1569,7 @@ debug_strfdatetime (const struct tm *tm, const parser_control *pc,
or '2016-19-2016' . These are the values as parsed from the user or '2016-19-2016' . These are the values as parsed from the user
string, before validation. string, before validation.
*/ */
int m = snprintf (buf,n,"(Y-M-D) %04d-%02d-%02d %02d:%02d:%02d", int m = nstrftime (buf, n, "(Y-M-D) %Y-%m-%d %H:%M:%S", tm, 0, 0);
tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec);
/* if parser_control information was provided (for timezone), /* if parser_control information was provided (for timezone),
and there's enough space in the buffer - add timezone info */ and there's enough space in the buffer - add timezone info */
@@ -1655,10 +1627,13 @@ debug_mktime_not_ok (struct tm const *tm0, struct tm const *tm1,
const bool dst_shift = eq_sec && eq_min && !eq_hour const bool dst_shift = eq_sec && eq_min && !eq_hour
&& eq_mday && eq_month && eq_year; && eq_mday && eq_month && eq_year;
DEBUG0 (_("error: invalid date/time value:\n")); if (!pc->parse_datetime_debug)
DEBUG (_(" user provided time: '%s'\n"), return;
dbg_printf (_("error: invalid date/time value:\n"));
dbg_printf (_(" user provided time: '%s'\n"),
debug_strfdatetime (tm0, pc, tmp, sizeof (tmp))); debug_strfdatetime (tm0, pc, tmp, sizeof (tmp)));
DEBUG (_(" normalized time: '%s'\n"), dbg_printf (_(" normalized time: '%s'\n"),
debug_strfdatetime (tm1, pc, tmp, sizeof (tmp))); debug_strfdatetime (tm1, pc, tmp, sizeof (tmp)));
/* NOTEs: the format must be aligned with debug_strfdatetime() and the two /* NOTEs: the format must be aligned with debug_strfdatetime() and the two
DEBUG statements above. this string is not translated. */ DEBUG statements above. this string is not translated. */
@@ -1673,15 +1648,15 @@ debug_mktime_not_ok (struct tm const *tm0, struct tm const *tm1,
--i; --i;
tmp[i] = '\0'; tmp[i] = '\0';
} }
DEBUG ("%s\n", tmp); dbg_printf ("%s\n", tmp);
DEBUG0 (_(" possible reasons:\n")); dbg_printf (_(" possible reasons:\n"));
if (dst_shift) if (dst_shift)
DEBUG0 (_(" non-existing due to daylight-saving time;\n")); dbg_printf (_(" non-existing due to daylight-saving time;\n"));
if (!eq_mday && !eq_month) if (!eq_mday && !eq_month)
DEBUG0 (_(" invalid day/month combination;\n")); dbg_printf (_(" invalid day/month combination;\n"));
DEBUG0 (_(" numeric values overflow;\n")); dbg_printf (_(" numeric values overflow;\n"));
DEBUG (" %s\n",time_zone_seen?_("incorrect timezone") dbg_printf (" %s\n",time_zone_seen?_("incorrect timezone")
:_("missing timezone")); :_("missing timezone"));
} }
@@ -1699,14 +1674,21 @@ get_effective_timezone (void)
return (long int)lz; return (long int)lz;
} }
/* The original interface: run with debug=false */
bool
parse_datetime (struct timespec *result, char const *p,
struct timespec const *now)
{
return parse_datetime2 (result, p, now, 0);
}
/* Parse a date/time string, storing the resulting time value into *RESULT. /* Parse a date/time string, storing the resulting time value into *RESULT.
The string itself is pointed to by P. Return true if successful. The string itself is pointed to by P. Return true if successful.
P can be an incomplete or relative time specification; if so, use P can be an incomplete or relative time specification; if so, use
*NOW as the basis for the returned time. */ *NOW as the basis for the returned time. */
bool bool
parse_datetime (struct timespec *result, char const *p, parse_datetime2 (struct timespec *result, char const *p,
struct timespec const *now) struct timespec const *now, unsigned int flags)
{ {
time_t Start; time_t Start;
long int Start_ns; long int Start_ns;
@@ -1807,6 +1789,7 @@ parse_datetime (struct timespec *result, char const *p,
pc.local_zones_seen = 0; pc.local_zones_seen = 0;
pc.dsts_seen = 0; pc.dsts_seen = 0;
pc.zones_seen = 0; pc.zones_seen = 0;
pc.parse_datetime_debug = (flags & PARSE_DATETIME_DEBUG)!=0;
pc.debug_dates_seen = 0; pc.debug_dates_seen = 0;
pc.debug_days_seen = 0; pc.debug_days_seen = 0;
pc.debug_times_seen = 0; pc.debug_times_seen = 0;
@@ -1878,12 +1861,13 @@ parse_datetime (struct timespec *result, char const *p,
if (yyparse (&pc) != 0) if (yyparse (&pc) != 0)
{ {
DEBUG (_("error: parsing failed, stopped at '%s'\n"), pc.input); if (pc.parse_datetime_debug)
dbg_printf (_("error: parsing failed, stopped at '%s'\n"), pc.input);
goto fail; goto fail;
} }
/* determine effective timezone source */ /* determine effective timezone source */
if (parse_datetime_debug) if (pc.parse_datetime_debug)
{ {
long int tz = pc.debug_default_input_timezone; long int tz = pc.debug_default_input_timezone;
const char* tz_env; const char* tz_env;
@@ -1924,7 +1908,8 @@ parse_datetime (struct timespec *result, char const *p,
tz_src = _("system default"); tz_src = _("system default");
} }
PROGRESS (_("input timezone: %+03d:%02d (set from %s)\n"), if (pc.parse_datetime_debug)
dbg_printf (_("input timezone: %+03d:%02d (set from %s)\n"),
(int)(tz/60), abs ((int)tz)%60, tz_src); (int)(tz/60), abs ((int)tz)%60, tz_src);
} }
@@ -1936,23 +1921,23 @@ parse_datetime (struct timespec *result, char const *p,
if (1 < (pc.times_seen | pc.dates_seen | pc.days_seen | pc.dsts_seen if (1 < (pc.times_seen | pc.dates_seen | pc.days_seen | pc.dsts_seen
| (pc.local_zones_seen + pc.zones_seen))) | (pc.local_zones_seen + pc.zones_seen)))
{ {
if (parse_datetime_debug) if (pc.parse_datetime_debug)
{ {
if (pc.times_seen > 1) if (pc.times_seen > 1)
DEBUG0 ("error: seen multiple time parts\n"); dbg_printf ("error: seen multiple time parts\n");
if (pc.dates_seen > 1) if (pc.dates_seen > 1)
DEBUG0 ("error: seen multiple date parts\n"); dbg_printf ("error: seen multiple date parts\n");
if (pc.days_seen > 1) if (pc.days_seen > 1)
DEBUG0 ("error: seen multiple days parts\n"); dbg_printf ("error: seen multiple days parts\n");
if (pc.dsts_seen > 1) if (pc.dsts_seen > 1)
DEBUG0 ("error: seen multiple daylight-saving parts\n"); dbg_printf ("error: seen multiple daylight-saving parts\n");
if ( (pc.local_zones_seen + pc.zones_seen) > 1) if ( (pc.local_zones_seen + pc.zones_seen) > 1)
DEBUG0 ("error: seen multiple time-zone parts\n"); dbg_printf ("error: seen multiple time-zone parts\n");
} }
goto fail; goto fail;
} }
tm.tm_year = to_year (pc.year) - TM_YEAR_BASE; tm.tm_year = to_year (pc.year, pc.parse_datetime_debug) - TM_YEAR_BASE;
tm.tm_mon = pc.month - 1; tm.tm_mon = pc.month - 1;
tm.tm_mday = pc.day; tm.tm_mday = pc.day;
if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen)) if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen))
@@ -1962,13 +1947,15 @@ parse_datetime (struct timespec *result, char const *p,
{ {
const char* mrd = (pc.meridian==MERam)?"am": const char* mrd = (pc.meridian==MERam)?"am":
(pc.meridian==MERpm)?"pm":""; (pc.meridian==MERpm)?"pm":"";
DEBUG (_("error: invalid hour %ld%s\n"), pc.hour, mrd); if (pc.parse_datetime_debug)
dbg_printf (_("error: invalid hour %ld%s\n"), pc.hour, mrd);
goto fail; goto fail;
} }
tm.tm_min = pc.minutes; tm.tm_min = pc.minutes;
tm.tm_sec = pc.seconds.tv_sec; tm.tm_sec = pc.seconds.tv_sec;
PROGRESS (_("using %s time as starting value: '%s'\n"), if (pc.parse_datetime_debug)
dbg_printf (_("using %s time as starting value: '%s'\n"),
(pc.times_seen)?_("specified"):_("current"), (pc.times_seen)?_("specified"):_("current"),
debug_strftime (&tm,dbg_tm,sizeof (dbg_tm))); debug_strftime (&tm,dbg_tm,sizeof (dbg_tm)));
} }
@@ -1976,7 +1963,8 @@ parse_datetime (struct timespec *result, char const *p,
{ {
tm.tm_hour = tm.tm_min = tm.tm_sec = 0; tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
pc.seconds.tv_nsec = 0; pc.seconds.tv_nsec = 0;
DEBUG0 ("warning: using midnight as starting time: 00:00:00\n"); if (pc.parse_datetime_debug)
dbg_printf ("warning: using midnight as starting time: 00:00:00\n");
} }
/* Let mktime deduce tm_isdst if we have an absolute time stamp. */ /* Let mktime deduce tm_isdst if we have an absolute time stamp. */
@@ -1996,7 +1984,7 @@ parse_datetime (struct timespec *result, char const *p,
{ {
if (! pc.zones_seen) if (! pc.zones_seen)
{ {
DEBUG_MKTIME_NOT_OK (&tm0, &tm, &pc, pc.zones_seen); debug_mktime_not_ok (&tm0, &tm, &pc, pc.zones_seen);
goto fail; goto fail;
} }
@@ -2025,7 +2013,8 @@ parse_datetime (struct timespec *result, char const *p,
if (setenv ("TZ", tz1buf, 1) != 0) if (setenv ("TZ", tz1buf, 1) != 0)
{ {
/* TODO: was warn () + print errno? */ /* TODO: was warn () + print errno? */
DEBUG (_("error: setenv('TZ','%s') failed\n"), tz1buf); if (pc.parse_datetime_debug)
dbg_printf (_("error: setenv('TZ','%s') failed\n"), tz1buf);
goto fail; goto fail;
} }
@@ -2034,7 +2023,7 @@ parse_datetime (struct timespec *result, char const *p,
Start = mktime (&tm); Start = mktime (&tm);
if (! mktime_ok (&tm0, &tm, Start)) if (! mktime_ok (&tm0, &tm, Start))
{ {
DEBUG_MKTIME_NOT_OK (&tm0, &tm, &pc, pc.zones_seen); debug_mktime_not_ok (&tm0, &tm, &pc, pc.zones_seen);
goto fail; goto fail;
} }
@@ -2051,44 +2040,53 @@ parse_datetime (struct timespec *result, char const *p,
Start = mktime (&tm); Start = mktime (&tm);
if (Start == (time_t) -1) if (Start == (time_t) -1)
{ {
DEBUG (_("error: day '%s' (day ordinal=%ld number=%d) " \ if (pc.parse_datetime_debug)
dbg_printf (_("error: day '%s' (day ordinal=%ld number=%d) " \
"resulted in an invalid date: '%s'\n"), "resulted in an invalid date: '%s'\n"),
str_days (&pc,dbg_ord,sizeof (dbg_ord)), str_days (&pc,dbg_ord,sizeof (dbg_ord)),
pc.day_ordinal,pc.day_number, pc.day_ordinal,pc.day_number,
debug_strfdatetime (&tm, &pc, dbg_tm,sizeof (dbg_tm))); debug_strfdatetime (&tm, &pc, dbg_tm,
sizeof (dbg_tm)));
goto fail; goto fail;
} }
PROGRESS (_("new start date: '%s' is '%s'\n"), if (pc.parse_datetime_debug)
dbg_printf (_("new start date: '%s' is '%s'\n"),
str_days (&pc,dbg_ord,sizeof (dbg_ord)), str_days (&pc,dbg_ord,sizeof (dbg_ord)),
debug_strfdatetime (&tm, &pc, dbg_tm,sizeof (dbg_tm))); debug_strfdatetime (&tm, &pc, dbg_tm,sizeof (dbg_tm)));
} }
if (pc.parse_datetime_debug)
{
if (!pc.dates_seen && !pc.days_seen) if (!pc.dates_seen && !pc.days_seen)
PROGRESS (_("using current date as starting value: '%s'\n"), dbg_printf (_("using current date as starting value: '%s'\n"),
debug_strfdate (&tm,dbg_tm,sizeof (dbg_tm))); debug_strfdate (&tm,dbg_tm,sizeof (dbg_tm)));
if (pc.days_seen && pc.dates_seen) if (pc.days_seen && pc.dates_seen)
DEBUG (_("warning: day (%s) ignored when explicit dates are given\n"), dbg_printf (_("warning: day (%s) ignored when explicit dates " \
"are given\n"),
str_days (&pc,dbg_ord,sizeof (dbg_ord))); str_days (&pc,dbg_ord,sizeof (dbg_ord)));
PROGRESS (_("starting date/time: '%s'\n"), dbg_printf (_("starting date/time: '%s'\n"),
debug_strfdatetime (&tm, &pc, dbg_tm,sizeof (dbg_tm))); debug_strfdatetime (&tm, &pc, dbg_tm,sizeof (dbg_tm)));
}
/* Add relative date. */ /* Add relative date. */
if (pc.rel.year | pc.rel.month | pc.rel.day) if (pc.rel.year | pc.rel.month | pc.rel.day)
{
if (pc.parse_datetime_debug)
{ {
if ((pc.rel.year != 0 || pc.rel.month !=0) && tm.tm_mday==1) if ((pc.rel.year != 0 || pc.rel.month !=0) && tm.tm_mday==1)
DEBUG0 ("warning: when adding relative months/years, " \ dbg_printf (_("warning: when adding relative months/years, " \
"it is recommended to specify the 15th of the months\n"); "it is recommended to specify the 15th of the " \
"months\n"));
if (pc.rel.day != 0 && tm.tm_hour==0) if (pc.rel.day != 0 && tm.tm_hour==0)
DEBUG0 ("warning: when adding relative days, " \ dbg_printf (_("warning: when adding relative days, " \
"it is recommended to specify 12:00pm\n"); "it is recommended to specify 12:00pm\n"));
}
int year = tm.tm_year + pc.rel.year; int year = tm.tm_year + pc.rel.year;
int month = tm.tm_mon + pc.rel.month; int month = tm.tm_mon + pc.rel.month;
@@ -2098,7 +2096,8 @@ parse_datetime (struct timespec *result, char const *p,
| ((day < tm.tm_mday) ^ (pc.rel.day < 0))) | ((day < tm.tm_mday) ^ (pc.rel.day < 0)))
{ {
/* TODO: what is the actual error? int-value wrap-around? */ /* TODO: what is the actual error? int-value wrap-around? */
DEBUG (_("error: %s:%d\n"), __FILE__,__LINE__); if (pc.parse_datetime_debug)
dbg_printf (_("error: %s:%d\n"), __FILE__,__LINE__);
goto fail; goto fail;
} }
@@ -2112,18 +2111,24 @@ parse_datetime (struct timespec *result, char const *p,
Start = mktime (&tm); Start = mktime (&tm);
if (Start == (time_t) -1) if (Start == (time_t) -1)
{ {
DEBUG (_("error: adding relative date resulted " \ if (pc.parse_datetime_debug)
dbg_printf(_("error: adding relative date resulted " \
"in an invalid date: '%s'\n"), "in an invalid date: '%s'\n"),
debug_strfdatetime (&tm, &pc, dbg_tm, sizeof (dbg_tm))); debug_strfdatetime (&tm, &pc, dbg_tm,
sizeof (dbg_tm)));
goto fail; goto fail;
} }
PROGRESS (_("after date adjustment "\ if (pc.parse_datetime_debug)
{
dbg_printf (_("after date adjustment " \
"(%+ld years, %+ld months, %+ld days),\n"), "(%+ld years, %+ld months, %+ld days),\n"),
pc.rel.year, pc.rel.month, pc.rel.day); pc.rel.year, pc.rel.month, pc.rel.day);
PROGRESS (_(" new date/time = '%s'\n"), dbg_printf (_(" new date/time = '%s'\n"),
debug_strfdatetime (&tm, &pc, dbg_tm, sizeof (dbg_tm))); debug_strfdatetime (&tm, &pc, dbg_tm,
sizeof (dbg_tm)));
}
} }
@@ -2141,7 +2146,8 @@ parse_datetime (struct timespec *result, char const *p,
if (! gmt) if (! gmt)
{ {
/* TODO: use 'warn(3)' + print errno ? */ /* TODO: use 'warn(3)' + print errno ? */
DEBUG (_("error: gmtime failed for t=%ld\n"),t); if (pc.parse_datetime_debug)
dbg_printf (_("error: gmtime failed for t=%ld\n"),t);
goto fail; goto fail;
} }
@@ -2150,7 +2156,8 @@ parse_datetime (struct timespec *result, char const *p,
t1 = Start - delta; t1 = Start - delta;
if ((Start < t1) != (delta < 0)) if ((Start < t1) != (delta < 0))
{ {
DEBUG (_("error: timezone %ld caused time_t overflow\n"), if (pc.parse_datetime_debug)
dbg_printf (_("error: timezone %ld caused time_t overflow\n"),
pc.time_zone); pc.time_zone);
goto fail; /* time_t overflow */ goto fail; /* time_t overflow */
@@ -2158,7 +2165,8 @@ parse_datetime (struct timespec *result, char const *p,
Start = t1; Start = t1;
} }
PROGRESS (_("'%s' = %ld epoch-seconds\n"), if (pc.parse_datetime_debug)
dbg_printf (_("'%s' = %ld epoch-seconds\n"),
debug_strfdatetime (&tm, &pc, dbg_tm, sizeof (dbg_tm)), debug_strfdatetime (&tm, &pc, dbg_tm, sizeof (dbg_tm)),
Start); Start);
@@ -2191,17 +2199,20 @@ parse_datetime (struct timespec *result, char const *p,
| ((t4 < t3) ^ (d4 < 0)) | ((t4 < t3) ^ (d4 < 0))
| (t5 != t4)) | (t5 != t4))
{ {
DEBUG0 (" error: adding relative time caused an overflow\n"); if (pc.parse_datetime_debug)
dbg_printf (_("error: adding relative time caused an " \
"overflow\n"));
goto fail; goto fail;
} }
if (pc.rel.hour | pc.rel.minutes | pc.rel.seconds | pc.rel.ns ) if (pc.parse_datetime_debug
&& (pc.rel.hour | pc.rel.minutes | pc.rel.seconds | pc.rel.ns))
{ {
PROGRESS (_("after time adjustment " \ dbg_printf (_("after time adjustment (%+ld hours, " \
"(%+ld hours, %+ld minutes, %+ld seconds, %+ld ns),\n"), "%+ld minutes, %+ld seconds, %+ld ns),\n"),
pc.rel.hour,pc.rel.minutes,pc.rel.seconds,pc.rel.ns); pc.rel.hour,pc.rel.minutes,pc.rel.seconds,pc.rel.ns);
PROGRESS (_(" new time = %ld epoch-seconds\n"),t5); dbg_printf (_(" new time = %ld epoch-seconds\n"),t5);
} }
result->tv_sec = t5; result->tv_sec = t5;
@@ -2219,7 +2230,7 @@ parse_datetime (struct timespec *result, char const *p,
if (tz0 != tz0buf) if (tz0 != tz0buf)
free (tz0); free (tz0);
if (ok && parse_datetime_debug) if (ok && pc.parse_datetime_debug)
{ {
/* print local timezone AFTER restoring TZ (if tz_was_altered)*/ /* print local timezone AFTER restoring TZ (if tz_was_altered)*/
const long int otz = get_effective_timezone (); const long int otz = get_effective_timezone ();
@@ -2245,21 +2256,24 @@ parse_datetime (struct timespec *result, char const *p,
tz_src = _("system default"); tz_src = _("system default");
} }
PROGRESS (_("output timezone: %+03d:%02d (set from %s)\n"), if (pc.parse_datetime_debug)
{
dbg_printf (_("output timezone: %+03d:%02d (set from %s)\n"),
(int)(otz/60), abs ((int)otz)%60, tz_src); (int)(otz/60), abs ((int)otz)%60, tz_src);
PROGRESS (_("final: %ld.%09ld (epoch-seconds)\n"), dbg_printf (_("final: %ld.%09ld (epoch-seconds)\n"),
result->tv_sec,result->tv_nsec); result->tv_sec,result->tv_nsec);
struct tm const *gmt = gmtime (&result->tv_sec); struct tm const *gmt = gmtime (&result->tv_sec);
PROGRESS (_("final: %s (UTC0)\n"), dbg_printf (_("final: %s (UTC0)\n"),
debug_strfdatetime (gmt, NULL, dbg_tm, sizeof (dbg_tm))); debug_strfdatetime (gmt, NULL, dbg_tm, sizeof (dbg_tm)));
struct tm const *lmt = localtime (&result->tv_sec); struct tm const *lmt = localtime (&result->tv_sec);
PROGRESS (_("final: %s (output timezone TZ=%+03d:%02d)\n"), dbg_printf (_("final: %s (output timezone TZ=%+03d:%02d)\n"),
debug_strfdatetime (lmt, NULL, dbg_tm, sizeof (dbg_tm)), debug_strfdatetime (lmt, NULL, dbg_tm, sizeof (dbg_tm)),
(int)(otz/60), abs ((int)otz)%60); (int)(otz/60), abs ((int)otz)%60);
} }
}
return ok; return ok;
} }

View File

@@ -17,6 +17,7 @@ gettext-h
intprops intprops
mktime mktime
setenv setenv
strftime
unsetenv unsetenv
time time
timegm timegm