X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fgetdate.y;h=868f98303dd096f96e5d92a76c766a2ad6a59eb0;hb=35a32ee9550d22a932f1a71d89653e351405638d;hp=6ffee30b96ffb5a96162c45b69c6f44fca3cffb6;hpb=65248632b944a621e4c390de3e31b7421632354e;p=gnulib.git diff --git a/lib/getdate.y b/lib/getdate.y index 6ffee30b9..868f98303 100644 --- a/lib/getdate.y +++ b/lib/getdate.y @@ -1,6 +1,8 @@ %{ /* Parse a string into an internal time stamp. - Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + + Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 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 @@ -14,7 +16,7 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Originally written by Steven M. Bellovin while at the University of North Carolina at Chapel Hill. Later tweaked by @@ -36,7 +38,16 @@ #include "getdate.h" -#include +/* There's no need to extend the stack, so there's no need to involve + alloca. */ +#define YYSTACK_USE_ALLOCA 0 + +/* Tell Bison how much stack space is needed. 20 should be plenty for + this grammar, which is not right recursive. Beware setting it too + high, since that might cause problems on machines whose + implementations have lame stack-overflow checking. */ +#define YYMAXDEPTH 20 +#define YYINITDEPTH YYMAXDEPTH /* 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 @@ -164,12 +175,13 @@ typedef struct long int rel_seconds; long int rel_ns; - /* Counts of nonterminals of various flavors parsed so far. */ + /* Presence or counts of nonterminals of various flavors parsed so far. */ bool timespec_seen; + bool rels_seen; size_t dates_seen; size_t days_seen; size_t local_zones_seen; - size_t rels_seen; + size_t dsts_seen; size_t times_seen; size_t zones_seen; @@ -190,8 +202,8 @@ static long int time_zone_hhmm (textint, long int); %parse-param { parser_control *pc } %lex-param { parser_control *pc } -/* This grammar has 14 shift/reduce conflicts. */ -%expect 14 +/* This grammar has 20 shift/reduce conflicts. */ +%expect 20 %union { @@ -244,7 +256,7 @@ item: | day { pc->days_seen++; } | rel - { pc->rels_seen++; } + { pc->rels_seen = true; } | number ; @@ -295,14 +307,22 @@ time: local_zone: tLOCAL_ZONE - { pc->local_isdst = $1; } + { + pc->local_isdst = $1; + pc->dsts_seen += (0 < $1); + } | tLOCAL_ZONE tDST - { pc->local_isdst = $1 < 0 ? 1 : $1 + 1; } + { + pc->local_isdst = 1; + pc->dsts_seen += (0 < $1) + 1; + } ; zone: tZONE { pc->time_zone = $1; } + | tZONE relunit_snumber + { pc->time_zone = $1; pc->rels_seen = true; } | tZONE tSNUMBER o_colon_minutes { pc->time_zone = $1 + time_zone_hhmm ($2, $3); } | tDAYZONE @@ -426,54 +446,58 @@ relunit: { pc->rel_year += $1 * $2; } | tUNUMBER tYEAR_UNIT { pc->rel_year += $1.value * $2; } - | tSNUMBER tYEAR_UNIT - { pc->rel_year += $1.value * $2; } | tYEAR_UNIT { pc->rel_year += $1; } | tORDINAL tMONTH_UNIT { pc->rel_month += $1 * $2; } | tUNUMBER tMONTH_UNIT { pc->rel_month += $1.value * $2; } - | tSNUMBER tMONTH_UNIT - { pc->rel_month += $1.value * $2; } | tMONTH_UNIT { pc->rel_month += $1; } | tORDINAL tDAY_UNIT { pc->rel_day += $1 * $2; } | tUNUMBER tDAY_UNIT { pc->rel_day += $1.value * $2; } - | tSNUMBER tDAY_UNIT - { pc->rel_day += $1.value * $2; } | tDAY_UNIT { pc->rel_day += $1; } | tORDINAL tHOUR_UNIT { pc->rel_hour += $1 * $2; } | tUNUMBER tHOUR_UNIT { pc->rel_hour += $1.value * $2; } - | tSNUMBER tHOUR_UNIT - { pc->rel_hour += $1.value * $2; } | tHOUR_UNIT { pc->rel_hour += $1; } | tORDINAL tMINUTE_UNIT { pc->rel_minutes += $1 * $2; } | tUNUMBER tMINUTE_UNIT { pc->rel_minutes += $1.value * $2; } - | tSNUMBER tMINUTE_UNIT - { pc->rel_minutes += $1.value * $2; } | tMINUTE_UNIT { pc->rel_minutes += $1; } | tORDINAL tSEC_UNIT { pc->rel_seconds += $1 * $2; } | tUNUMBER tSEC_UNIT { pc->rel_seconds += $1.value * $2; } - | tSNUMBER tSEC_UNIT - { pc->rel_seconds += $1.value * $2; } | tSDECIMAL_NUMBER tSEC_UNIT { pc->rel_seconds += $1.tv_sec * $2; pc->rel_ns += $1.tv_nsec * $2; } | tUDECIMAL_NUMBER tSEC_UNIT { pc->rel_seconds += $1.tv_sec * $2; pc->rel_ns += $1.tv_nsec * $2; } | tSEC_UNIT { pc->rel_seconds += $1; } + | relunit_snumber + ; + +relunit_snumber: + tSNUMBER tYEAR_UNIT + { pc->rel_year += $1.value * $2; } + | tSNUMBER tMONTH_UNIT + { pc->rel_month += $1.value * $2; } + | tSNUMBER tDAY_UNIT + { pc->rel_day += $1.value * $2; } + | tSNUMBER tHOUR_UNIT + { pc->rel_hour += $1.value * $2; } + | tSNUMBER tMINUTE_UNIT + { pc->rel_minutes += $1.value * $2; } + | tSNUMBER tSEC_UNIT + { pc->rel_seconds += $1.value * $2; } ; seconds: signed_seconds | unsigned_seconds; @@ -493,7 +517,7 @@ unsigned_seconds: number: tUNUMBER { - if (pc->dates_seen + if (pc->dates_seen && ! pc->year.digits && ! pc->rels_seen && (pc->times_seen || 2 < $1.digits)) pc->year = $1; else @@ -627,6 +651,17 @@ static table const relative_time_table[] = { NULL, 0, 0 } }; +/* The universal time zone table. These labels can be used even for + time stamps that would not otherwise be valid, e.g., GMT time + stamps in London during summer. */ +static table const universal_time_zone_table[] = +{ + { "GMT", tZONE, HOUR ( 0) }, /* Greenwich Mean */ + { "UT", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */ + { "UTC", tZONE, HOUR ( 0) }, + { NULL, 0, 0 } +}; + /* The time zone table. This table is necessarily incomplete, as time zone abbreviations are ambiguous; e.g. Australians interpret "EST" as Eastern time in Australia, not as US Eastern Standard Time. @@ -634,9 +669,6 @@ static table const relative_time_table[] = abbreviations; use numeric abbreviations like `-0500' instead. */ static table const time_zone_table[] = { - { "GMT", tZONE, HOUR ( 0) }, /* Greenwich Mean */ - { "UT", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */ - { "UTC", tZONE, HOUR ( 0) }, { "WET", tZONE, HOUR ( 0) }, /* Western European */ { "WEST", tDAYZONE, HOUR ( 0) }, /* Western European Summer */ { "BST", tDAYZONE, HOUR ( 0) }, /* British Summer */ @@ -684,7 +716,7 @@ static table const time_zone_table[] = { "GST", tZONE, HOUR (10) }, /* Guam Standard */ { "NZST", tZONE, HOUR (12) }, /* New Zealand Standard */ { "NZDT", tDAYZONE, HOUR (12) }, /* New Zealand Daylight */ - { NULL, 0, 0 } + { NULL, 0, 0 } }; /* Military time zone table. */ @@ -769,7 +801,12 @@ lookup_zone (parser_control const *pc, char const *name) { table const *tp; - /* Try local zone abbreviations first; they're more likely to be right. */ + for (tp = universal_time_zone_table; tp->name; tp++) + if (strcmp (name, tp->name) == 0) + return tp; + + /* Try local zone abbreviations before those in time_zone_table, as + the local ones are more likely to be right. */ for (tp = pc->local_time_zone_table; tp->name; tp++) if (strcmp (name, tp->name) == 0) return tp; @@ -1116,8 +1153,7 @@ get_date (struct timespec *result, char const *p, struct timespec const *now) if (! now) { - if (gettime (&gettime_buffer) != 0) - return false; + gettime (&gettime_buffer); now = &gettime_buffer; } @@ -1169,7 +1205,7 @@ get_date (struct timespec *result, char const *p, struct timespec const *now) pc.input = p; pc.year.value = tmp->tm_year; pc.year.value += TM_YEAR_BASE; - pc.year.digits = 4; + pc.year.digits = 0; pc.month = tmp->tm_mon + 1; pc.day = tmp->tm_mday; pc.hour = tmp->tm_hour; @@ -1187,11 +1223,12 @@ get_date (struct timespec *result, char const *p, struct timespec const *now) pc.rel_month = 0; pc.rel_year = 0; pc.timespec_seen = false; + pc.rels_seen = false; pc.dates_seen = 0; pc.days_seen = 0; - pc.rels_seen = 0; pc.times_seen = 0; pc.local_zones_seen = 0; + pc.dsts_seen = 0; pc.zones_seen = 0; #if HAVE_STRUCT_TM_TM_ZONE @@ -1259,9 +1296,8 @@ get_date (struct timespec *result, char const *p, struct timespec const *now) *result = pc.seconds; else { - if (1 < pc.times_seen || 1 < pc.dates_seen || 1 < pc.days_seen - || 1 < (pc.local_zones_seen + pc.zones_seen) - || (pc.local_zones_seen && 1 < pc.local_isdst)) + if (1 < (pc.times_seen | pc.dates_seen | pc.days_seen | pc.dsts_seen + | (pc.local_zones_seen + pc.zones_seen))) goto fail; tm.tm_year = to_year (pc.year) - TM_YEAR_BASE; @@ -1282,7 +1318,7 @@ get_date (struct timespec *result, char const *p, struct timespec const *now) } /* Let mktime deduce tm_isdst if we have an absolute time stamp. */ - if (pc.dates_seen | pc.days_seen | pc.times_seen) + if (!pc.rels_seen) tm.tm_isdst = -1; /* But if the input explicitly specifies local time with or without