X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fgetdate.y;h=57374f1d4fb176ba32c72052f5ecdf4553736974;hb=dd469821917cebe0abde6601b2ba7cd887bc498f;hp=2f72f045a32e1533acb56d7bdd3ac399f22c4383;hpb=aa33a4bea6151c466f7728cfe222ea753567a1b5;p=gnulib.git diff --git a/lib/getdate.y b/lib/getdate.y index 2f72f045a..57374f1d4 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 @@ -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 @@ -108,6 +119,7 @@ representation. */ typedef struct { + bool negative; long int value; size_t digits; } textint; @@ -179,6 +191,7 @@ typedef struct union YYSTYPE; static int yylex (union YYSTYPE *, parser_control *); static int yyerror (parser_control *, char *); +static long int time_zone_hhmm (textint, long int); %} @@ -188,8 +201,8 @@ static int yyerror (parser_control *, char *); %parse-param { parser_control *pc } %lex-param { parser_control *pc } -/* This grammar has 13 shift/reduce conflicts. */ -%expect 13 +/* This grammar has 14 shift/reduce conflicts. */ +%expect 14 %union { @@ -201,12 +214,13 @@ static int yyerror (parser_control *, char *); %token tAGO tDST %token tDAY tDAY_UNIT tDAYZONE tHOUR_UNIT tLOCAL_ZONE tMERIDIAN -%token tMINUTE_UNIT tMONTH tMONTH_UNIT tSEC_UNIT tYEAR_UNIT tZONE +%token tMINUTE_UNIT tMONTH tMONTH_UNIT tORDINAL +%token tSEC_UNIT tYEAR_UNIT tZONE %token tSNUMBER tUNUMBER %token tSDECIMAL_NUMBER tUDECIMAL_NUMBER -%type o_merid +%type o_colon_minutes o_merid %type seconds signed_seconds unsigned_seconds %% @@ -262,7 +276,7 @@ time: pc->seconds.tv_nsec = 0; pc->meridian = $4; } - | tUNUMBER ':' tUNUMBER tSNUMBER + | tUNUMBER ':' tUNUMBER tSNUMBER o_colon_minutes { pc->hour = $1.value; pc->minutes = $3.value; @@ -270,7 +284,7 @@ time: pc->seconds.tv_nsec = 0; pc->meridian = MER24; pc->zones_seen++; - pc->time_zone = $4.value % 100 + ($4.value / 100) * 60; + pc->time_zone = time_zone_hhmm ($4, $5); } | tUNUMBER ':' tUNUMBER ':' unsigned_seconds o_merid { @@ -279,14 +293,14 @@ time: pc->seconds = $5; pc->meridian = $6; } - | tUNUMBER ':' tUNUMBER ':' unsigned_seconds tSNUMBER + | tUNUMBER ':' tUNUMBER ':' unsigned_seconds tSNUMBER o_colon_minutes { pc->hour = $1.value; pc->minutes = $3.value; pc->seconds = $5; pc->meridian = MER24; pc->zones_seen++; - pc->time_zone = $6.value % 100 + ($6.value / 100) * 60; + pc->time_zone = time_zone_hhmm ($6, $7); } ; @@ -300,6 +314,8 @@ local_zone: zone: tZONE { pc->time_zone = $1; } + | tZONE tSNUMBER o_colon_minutes + { pc->time_zone = $1 + time_zone_hhmm ($2, $3); } | tDAYZONE { pc->time_zone = $1 + 60; } | tZONE tDST @@ -317,6 +333,11 @@ day: pc->day_ordinal = 1; pc->day_number = $1; } + | tORDINAL tDAY + { + pc->day_ordinal = $1; + pc->day_number = $2; + } | tUNUMBER tDAY { pc->day_ordinal = $1.value; @@ -412,36 +433,48 @@ rel: ; relunit: - tUNUMBER tYEAR_UNIT + tORDINAL tYEAR_UNIT + { 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 @@ -505,6 +538,13 @@ number: } ; +o_colon_minutes: + /* empty */ + { $$ = -1; } + | ':' tUNUMBER + { $$ = $2.value; } + ; + o_merid: /* empty */ { $$ = MER24; } @@ -579,21 +619,21 @@ static table const relative_time_table[] = { "YESTERDAY",tDAY_UNIT, -1 }, { "TODAY", tDAY_UNIT, 0 }, { "NOW", tDAY_UNIT, 0 }, - { "LAST", tUNUMBER, -1 }, - { "THIS", tUNUMBER, 0 }, - { "NEXT", tUNUMBER, 1 }, - { "FIRST", tUNUMBER, 1 }, -/*{ "SECOND", tUNUMBER, 2 }, */ - { "THIRD", tUNUMBER, 3 }, - { "FOURTH", tUNUMBER, 4 }, - { "FIFTH", tUNUMBER, 5 }, - { "SIXTH", tUNUMBER, 6 }, - { "SEVENTH", tUNUMBER, 7 }, - { "EIGHTH", tUNUMBER, 8 }, - { "NINTH", tUNUMBER, 9 }, - { "TENTH", tUNUMBER, 10 }, - { "ELEVENTH", tUNUMBER, 11 }, - { "TWELFTH", tUNUMBER, 12 }, + { "LAST", tORDINAL, -1 }, + { "THIS", tORDINAL, 0 }, + { "NEXT", tORDINAL, 1 }, + { "FIRST", tORDINAL, 1 }, +/*{ "SECOND", tORDINAL, 2 }, */ + { "THIRD", tORDINAL, 3 }, + { "FOURTH", tORDINAL, 4 }, + { "FIFTH", tORDINAL, 5 }, + { "SIXTH", tORDINAL, 6 }, + { "SEVENTH", tORDINAL, 7 }, + { "EIGHTH", tORDINAL, 8 }, + { "NINTH", tORDINAL, 9 }, + { "TENTH", tORDINAL, 10 }, + { "ELEVENTH", tORDINAL, 11 }, + { "TWELFTH", tORDINAL, 12 }, { "AGO", tAGO, 1 }, { NULL, 0, 0 } }; @@ -691,6 +731,19 @@ static table const military_table[] = +/* Convert a time zone expressed as HH:MM into an integer count of + minutes. If MM is negative, then S is of the form HHMM and needs + to be picked apart; otherwise, S is of the form HH. */ + +static long int +time_zone_hhmm (textint s, long int mm) +{ + if (mm < 0) + return (s.value / 100) * 60 + s.value % 100; + else + return s.value * 60 + (s.negative ? -mm : mm); +} + static int to_hour (long int hours, int meridian) { @@ -942,6 +995,7 @@ yylex (YYSTYPE *lvalp, parser_control *pc) } else { + lvalp->textintval.negative = sign < 0; if (sign < 0) { lvalp->textintval.value = - value; @@ -1073,8 +1127,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; }