X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=lib%2Fgetdate.y;h=3c4a04000f676a754aa9a15580d7a16fc76bb694;hb=1ffb4377a444fb7150030acfe843bc20cfba5d5a;hp=4b7c2e9c8efb66ad84e1f560f5a0f29e0eb68d7d;hpb=3a19b8b0df660ab893ebb9ac5a3614fd196c9135;p=chaz%2Ftar diff --git a/lib/getdate.y b/lib/getdate.y index 4b7c2e9..3c4a040 100644 --- a/lib/getdate.y +++ b/lib/getdate.y @@ -1,6 +1,6 @@ %{ /* Parse a string into an internal time stamp. - Copyright 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2002, 2003 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,11 +27,10 @@ #ifdef HAVE_CONFIG_H # include -# ifdef HAVE_ALLOCA_H -# include -# endif #endif +#include + /* Since the code of getdate.y is not included in the Emacs executable itself, there is no need to #define static in this file. Even if the code were included in the Emacs executable, it probably @@ -63,10 +62,9 @@ - Its arg may be any int or unsigned int; it need not be an unsigned char. - It's guaranteed to evaluate its argument exactly once. - It's typically faster. - Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that - only '0' through '9' are digits. Prefer ISDIGIT to ISDIGIT_LOCALE unless - it's important to use the locale's definition of `digit' even when the - host does not conform to Posix. */ + POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to + ISDIGIT_LOCALE unless it's important to use the locale's definition + of `digit' even when the host does not conform to POSIX. */ #define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) #if STDC_HEADERS || HAVE_STRING_H @@ -85,7 +83,7 @@ #define TM_YEAR_BASE 1900 #define HOUR(x) ((x) * 60) - + /* An integer value, and the number of digits in its textual representation. */ typedef struct @@ -168,7 +166,7 @@ static int yylex (); /* This grammar has 13 shift/reduce conflicts. */ %expect 13 - + %union { int intval; @@ -378,19 +376,19 @@ relunit: | tSNUMBER tDAY_UNIT { PC.rel_day += $1.value * $2; } | tDAY_UNIT - { PC.rel_day += $1 } + { PC.rel_day += $1; } | tUNUMBER tHOUR_UNIT { PC.rel_hour += $1.value * $2; } | tSNUMBER tHOUR_UNIT { PC.rel_hour += $1.value * $2; } | tHOUR_UNIT - { PC.rel_hour += $1 } + { PC.rel_hour += $1; } | tUNUMBER tMINUTE_UNIT { PC.rel_minutes += $1.value * $2; } | tSNUMBER tMINUTE_UNIT { PC.rel_minutes += $1.value * $2; } | tMINUTE_UNIT - { PC.rel_minutes += $1 } + { PC.rel_minutes += $1; } | tUNUMBER tSEC_UNIT { PC.rel_seconds += $1.value * $2; } | tSNUMBER tSEC_UNIT @@ -448,6 +446,7 @@ o_merid: may define-away `const'. We want the prototype for get_date to have the same signature as the function definition. */ #include "getdate.h" +#include "unlocked-io.h" #ifndef gmtime struct tm *gmtime (); @@ -908,7 +907,7 @@ get_date (const char *p, const time_t *now) pc.local_zones_seen = 0; pc.zones_seen = 0; -#if HAVE_TM_ZONE +#if HAVE_STRUCT_TM_TM_ZONE pc.local_time_zone_table[0].name = tmp->tm_zone; pc.local_time_zone_table[0].type = tLOCAL_ZONE; pc.local_time_zone_table[0].value = tmp->tm_isdst; @@ -987,13 +986,11 @@ get_date (const char *p, const time_t *now) { tm.tm_hour = tm.tm_min = tm.tm_sec = 0; } - tm.tm_hour += pc.rel_hour; - tm.tm_min += pc.rel_minutes; - tm.tm_sec += pc.rel_seconds; /* Let mktime deduce tm_isdst if we have an absolute time stamp, or if the relative time stamp mentions days, months, or years. */ - if (pc.dates_seen | pc.days_seen | pc.times_seen | pc.rel_day | pc.rel_month | pc.rel_year) + if (pc.dates_seen | pc.days_seen | pc.times_seen | pc.rel_day + | pc.rel_month | pc.rel_year) tm.tm_isdst = -1; /* But if the input explicitly specifies local time with or without @@ -1040,6 +1037,7 @@ get_date (const char *p, const time_t *now) { tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7 + 7 * (pc.day_ordinal - (0 < pc.day_ordinal))); + tm.tm_isdst = -1; Start = mktime (&tm); if (Start == (time_t) -1) return Start; @@ -1061,6 +1059,29 @@ get_date (const char *p, const time_t *now) Start -= delta; } + /* Add relative hours, minutes, and seconds. Ignore leap seconds; + i.e. "+ 10 minutes" means 600 seconds, even if one of them is a + leap second. Typically this is not what the user wants, but it's + too hard to do it the other way, because the time zone indicator + must be applied before relative times, and if mktime is applied + again the time zone will be lost. */ + { + time_t t0 = Start; + long d1 = 60 * 60 * (long) pc.rel_hour; + time_t t1 = t0 + d1; + long d2 = 60 * (long) pc.rel_minutes; + time_t t2 = t1 + d2; + int d3 = pc.rel_seconds; + time_t t3 = t2 + d3; + if ((d1 / (60 * 60) ^ pc.rel_hour) + | (d2 / 60 ^ pc.rel_minutes) + | ((t0 + d1 < t0) ^ (d1 < 0)) + | ((t1 + d2 < t1) ^ (d2 < 0)) + | ((t2 + d3 < t2) ^ (d3 < 0))) + return -1; + Start = t3; + } + return Start; }