projects
/
gnulib.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
array-oset, linkedhash-list, rbtree-oset: no need for 'inline'
[gnulib.git]
/
lib
/
parse-datetime.y
diff --git
a/lib/parse-datetime.y
b/lib/parse-datetime.y
index
0700852
..
4d9f65a
100644
(file)
--- a/
lib/parse-datetime.y
+++ b/
lib/parse-datetime.y
@@
-1,7
+1,7
@@
%{
/* Parse a string into an internal time stamp.
%{
/* Parse a string into an internal time stamp.
- Copyright (C) 1999-2000, 2002-201
1
Free Software Foundation, Inc.
+ Copyright (C) 1999-2000, 2002-201
2
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
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
@@
-82,7
+82,7
@@
- It's typically faster.
POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
isdigit unless it's important to use the locale's definition
- It's typically faster.
POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
isdigit unless it's important to use the locale's definition
- of
`digit'
even when the host does not conform to POSIX. */
+ of
"digit"
even when the host does not conform to POSIX. */
#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
/* Shift A right by B bits portably, by dividing A by 2**B and
#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
/* Shift A right by B bits portably, by dividing A by 2**B and
@@
-113,13
+113,10
@@
typedef long int long_time_t;
typedef time_t long_time_t;
#endif
typedef time_t long_time_t;
#endif
-/* The attribute __pure__ was added in gcc 2.96. */
-#undef _GL_ATTRIBUTE_PURE
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
-# define _GL_ATTRIBUTE_PURE __attribute__ ((__pure__))
-#else
-# define _GL_ATTRIBUTE_PURE /* empty */
-#endif
+/* Convert a possibly-signed character to an unsigned character. This is
+ a bit safer than casting to unsigned char, since it catches some type
+ errors that the cast doesn't. */
+static inline unsigned char to_uchar (char ch) { return ch; }
/* Lots of this code assumes time_t and time_t-like values fit into
long_time_t. */
/* Lots of this code assumes time_t and time_t-like values fit into
long_time_t. */
@@
-212,7
+209,7
@@
typedef struct
size_t times_seen;
size_t zones_seen;
size_t times_seen;
size_t zones_seen;
- /* Table of local time zone abbrevations, terminated by a null entry. */
+ /* Table of local time zone abbrev
i
ations, terminated by a null entry. */
table local_time_zone_table[3];
} parser_control;
table local_time_zone_table[3];
} parser_control;
@@
-293,8
+290,8
@@
set_hhmmss (parser_control *pc, long int hour, long int minutes,
%parse-param { parser_control *pc }
%lex-param { parser_control *pc }
%parse-param { parser_control *pc }
%lex-param { parser_control *pc }
-/* This grammar has
20
shift/reduce conflicts. */
-%expect
20
+/* This grammar has
31
shift/reduce conflicts. */
+%expect
31
%union
{
%union
{
@@
-304,7
+301,8
@@
set_hhmmss (parser_control *pc, long int hour, long int minutes,
relative_time rel;
}
relative_time rel;
}
-%token tAGO tDST
+%token <intval> tAGO
+%token tDST
%token tYEAR_UNIT tMONTH_UNIT tHOUR_UNIT tMINUTE_UNIT tSEC_UNIT
%token <intval> tDAY_UNIT tDAY_SHIFT
%token tYEAR_UNIT tMONTH_UNIT tHOUR_UNIT tMINUTE_UNIT tSEC_UNIT
%token <intval> tDAY_UNIT tDAY_SHIFT
@@
-315,7
+313,7
@@
set_hhmmss (parser_control *pc, long int hour, long int minutes,
%token <textintval> tSNUMBER tUNUMBER
%token <timespec> tSDECIMAL_NUMBER tUDECIMAL_NUMBER
%token <textintval> tSNUMBER tUNUMBER
%token <timespec> tSDECIMAL_NUMBER tUDECIMAL_NUMBER
-%type <intval> o_colon_minutes
o_merid
+%type <intval> o_colon_minutes
%type <timespec> seconds signed_seconds unsigned_seconds
%type <rel> relunit relunit_snumber dayshift
%type <timespec> seconds signed_seconds unsigned_seconds
%type <rel> relunit relunit_snumber dayshift
@@
-341,7
+339,9
@@
items:
;
item:
;
item:
- time
+ datetime
+ { pc->times_seen++; pc->dates_seen++; }
+ | time
{ pc->times_seen++; }
| local_zone
{ pc->local_zones_seen++; }
{ pc->times_seen++; }
| local_zone
{ pc->local_zones_seen++; }
@@
-356,35
+356,61
@@
item:
| hybrid
;
| hybrid
;
+datetime:
+ iso_8601_datetime
+ ;
+
+iso_8601_datetime:
+ iso_8601_date 'T' iso_8601_time
+ ;
+
time:
tUNUMBER tMERIDIAN
{
set_hhmmss (pc, $1.value, 0, 0, 0);
pc->meridian = $2;
}
time:
tUNUMBER tMERIDIAN
{
set_hhmmss (pc, $1.value, 0, 0, 0);
pc->meridian = $2;
}
- | tUNUMBER ':' tUNUMBER
o_merid
+ | tUNUMBER ':' tUNUMBER
tMERIDIAN
{
set_hhmmss (pc, $1.value, $3.value, 0, 0);
pc->meridian = $4;
}
{
set_hhmmss (pc, $1.value, $3.value, 0, 0);
pc->meridian = $4;
}
- | tUNUMBER ':' tUNUMBER
tSNUMBER o_colon_minutes
+ | tUNUMBER ':' tUNUMBER
':' unsigned_seconds tMERIDIAN
{
{
- set_hhmmss (pc, $1.value, $3.value, 0, 0);
+ set_hhmmss (pc, $1.value, $3.value, $5.tv_sec, $5.tv_nsec);
+ pc->meridian = $6;
+ }
+ | iso_8601_time
+ ;
+
+iso_8601_time:
+ tUNUMBER zone_offset
+ {
+ set_hhmmss (pc, $1.value, 0, 0, 0);
pc->meridian = MER24;
pc->meridian = MER24;
- pc->zones_seen++;
- pc->time_zone = time_zone_hhmm (pc, $4, $5);
}
}
- | tUNUMBER ':' tUNUMBER
':' unsigned_seconds o_merid
+ | tUNUMBER ':' tUNUMBER
o_zone_offset
{
{
- set_hhmmss (pc, $1.value, $3.value,
$5.tv_sec, $5.tv_nsec
);
- pc->meridian =
$6
;
+ set_hhmmss (pc, $1.value, $3.value,
0, 0
);
+ pc->meridian =
MER24
;
}
}
- | tUNUMBER ':' tUNUMBER ':' unsigned_seconds
tSNUMBER o_colon_minutes
+ | tUNUMBER ':' tUNUMBER ':' unsigned_seconds
o_zone_offset
{
set_hhmmss (pc, $1.value, $3.value, $5.tv_sec, $5.tv_nsec);
pc->meridian = MER24;
{
set_hhmmss (pc, $1.value, $3.value, $5.tv_sec, $5.tv_nsec);
pc->meridian = MER24;
+ }
+ ;
+
+o_zone_offset:
+ /* empty */
+ | zone_offset
+ ;
+
+zone_offset:
+ tSNUMBER o_colon_minutes
+ {
pc->zones_seen++;
pc->zones_seen++;
- pc->time_zone = time_zone_hhmm (pc, $
6, $7
);
+ pc->time_zone = time_zone_hhmm (pc, $
1, $2
);
}
;
}
;
@@
-401,12
+427,19
@@
local_zone:
}
;
}
;
+/* Note 'T' is a special case, as it is used as the separator in ISO
+ 8601 date and time of day representation. */
zone:
tZONE
{ pc->time_zone = $1; }
zone:
tZONE
{ pc->time_zone = $1; }
+ | 'T'
+ { pc->time_zone = HOUR(7); }
| tZONE relunit_snumber
{ pc->time_zone = $1;
apply_relative_time (pc, $2, 1); }
| tZONE relunit_snumber
{ pc->time_zone = $1;
apply_relative_time (pc, $2, 1); }
+ | 'T' relunit_snumber
+ { pc->time_zone = HOUR(7);
+ apply_relative_time (pc, $2, 1); }
| tZONE tSNUMBER o_colon_minutes
{ pc->time_zone = $1 + time_zone_hhmm (pc, $2, $3); }
| tDAYZONE
| tZONE tSNUMBER o_colon_minutes
{ pc->time_zone = $1 + time_zone_hhmm (pc, $2, $3); }
| tDAYZONE
@@
-464,13
+497,6
@@
date:
pc->year = $5;
}
}
pc->year = $5;
}
}
- | tUNUMBER tSNUMBER tSNUMBER
- {
- /* ISO 8601 format. YYYY-MM-DD. */
- pc->year = $1;
- pc->month = -$2.value;
- pc->day = -$3.value;
- }
| tUNUMBER tMONTH tSNUMBER
{
/* e.g. 17-JUN-1992. */
| tUNUMBER tMONTH tSNUMBER
{
/* e.g. 17-JUN-1992. */
@@
-509,11
+535,22
@@
date:
pc->month = $2;
pc->year = $3;
}
pc->month = $2;
pc->year = $3;
}
+ | iso_8601_date
+ ;
+
+iso_8601_date:
+ tUNUMBER tSNUMBER tSNUMBER
+ {
+ /* ISO 8601 format. YYYY-MM-DD. */
+ pc->year = $1;
+ pc->month = -$2.value;
+ pc->day = -$3.value;
+ }
;
rel:
relunit tAGO
;
rel:
relunit tAGO
- { apply_relative_time (pc, $1,
-1
); }
+ { apply_relative_time (pc, $1,
$2
); }
| relunit
{ apply_relative_time (pc, $1, 1); }
| dayshift
| relunit
{ apply_relative_time (pc, $1, 1); }
| dayshift
@@
-620,13
+657,6
@@
o_colon_minutes:
{ $$ = $2.value; }
;
{ $$ = $2.value; }
;
-o_merid:
- /* empty */
- { $$ = MER24; }
- | tMERIDIAN
- { $$ = $1; }
- ;
-
%%
static table const meridian_table[] =
%%
static table const meridian_table[] =
@@
-709,7
+739,8
@@
static table const relative_time_table[] =
{ "TENTH", tORDINAL, 10 },
{ "ELEVENTH", tORDINAL, 11 },
{ "TWELFTH", tORDINAL, 12 },
{ "TENTH", tORDINAL, 10 },
{ "ELEVENTH", tORDINAL, 11 },
{ "TWELFTH", tORDINAL, 12 },
- { "AGO", tAGO, 1 },
+ { "AGO", tAGO, -1 },
+ { "HENCE", tAGO, 1 },
{ NULL, 0, 0 }
};
{ NULL, 0, 0 }
};
@@
-728,7
+759,7
@@
static table const universal_time_zone_table[] =
zone abbreviations are ambiguous; e.g. Australians interpret "EST"
as Eastern time in Australia, not as US Eastern Standard Time.
You cannot rely on parse_datetime to handle arbitrary time zone
zone abbreviations are ambiguous; e.g. Australians interpret "EST"
as Eastern time in Australia, not as US Eastern Standard Time.
You cannot rely on parse_datetime to handle arbitrary time zone
- abbreviations; use numeric abbreviations like
`-0500'
instead. */
+ abbreviations; use numeric abbreviations like
"-0500"
instead. */
static table const time_zone_table[] =
{
{ "WET", tZONE, HOUR ( 0) }, /* Western European */
static table const time_zone_table[] =
{
{ "WET", tZONE, HOUR ( 0) }, /* Western European */
@@
-781,7
+812,10
@@
static table const time_zone_table[] =
{ NULL, 0, 0 }
};
{ NULL, 0, 0 }
};
-/* Military time zone table. */
+/* Military time zone table.
+
+ Note 'T' is a special case, as it is used as the separator in ISO
+ 8601 date and time of day representation. */
static table const military_table[] =
{
{ "A", tZONE, -HOUR ( 1) },
static table const military_table[] =
{
{ "A", tZONE, -HOUR ( 1) },
@@
-802,7
+836,7
@@
static table const military_table[] =
{ "Q", tZONE, HOUR ( 4) },
{ "R", tZONE, HOUR ( 5) },
{ "S", tZONE, HOUR ( 6) },
{ "Q", tZONE, HOUR ( 4) },
{ "R", tZONE, HOUR ( 5) },
{ "S", tZONE, HOUR ( 6) },
- { "T",
tZONE, HOUR ( 7)
},
+ { "T",
'T', 0
},
{ "U", tZONE, HOUR ( 8) },
{ "V", tZONE, HOUR ( 9) },
{ "W", tZONE, HOUR (10) },
{ "U", tZONE, HOUR ( 8) },
{ "V", tZONE, HOUR ( 9) },
{ "W", tZONE, HOUR (10) },
@@
-1127,7
+1161,7
@@
yylex (YYSTYPE *lvalp, parser_control *pc)
do
{
do
{
- if (p
< buff +
sizeof buff - 1)
+ if (p
- buff <
sizeof buff - 1)
*p++ = c;
c = *++pc->input;
}
*p++ = c;
c = *++pc->input;
}
@@
-1142,7
+1176,8
@@
yylex (YYSTYPE *lvalp, parser_control *pc)
}
if (c != '(')
}
if (c != '(')
- return *pc->input++;
+ return to_uchar (*pc->input++);
+
count = 0;
do
{
count = 0;
do
{
@@
-1365,7
+1400,7
@@
parse_datetime (struct timespec *result, char const *p,
&& ! strcmp (pc.local_time_zone_table[0].name,
pc.local_time_zone_table[1].name))
{
&& ! strcmp (pc.local_time_zone_table[0].name,
pc.local_time_zone_table[1].name))
{
- /* This locale uses the same abbrevation for standard and
+ /* This locale uses the same abbrev
i
ation for standard and
daylight times. So if we see that abbreviation, we don't
know whether it's daylight time. */
pc.local_time_zone_table[0].value = -1;
daylight times. So if we see that abbreviation, we don't
know whether it's daylight time. */
pc.local_time_zone_table[0].value = -1;