137 |
|
|
138 |
enum { BILLION = 1000000000, LOG10_BILLION = 9 }; |
enum { BILLION = 1000000000, LOG10_BILLION = 9 }; |
139 |
|
|
140 |
|
/* Relative times. */ |
141 |
|
typedef struct |
142 |
|
{ |
143 |
|
/* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */ |
144 |
|
long int year; |
145 |
|
long int month; |
146 |
|
long int day; |
147 |
|
long int hour; |
148 |
|
long int minutes; |
149 |
|
long int seconds; |
150 |
|
long int ns; |
151 |
|
} relative_time; |
152 |
|
|
153 |
|
#if HAVE_COMPOUND_LITERALS |
154 |
|
# define RELATIVE_TIME_0 ((relative_time) { 0, 0, 0, 0, 0, 0, 0 }) |
155 |
|
#else |
156 |
|
static relative_time const RELATIVE_TIME_0; |
157 |
|
#endif |
158 |
|
|
159 |
/* Information passed to and from the parser. */ |
/* Information passed to and from the parser. */ |
160 |
typedef struct |
typedef struct |
161 |
{ |
{ |
186 |
struct timespec seconds; /* includes nanoseconds */ |
struct timespec seconds; /* includes nanoseconds */ |
187 |
|
|
188 |
/* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */ |
/* Relative year, month, day, hour, minutes, seconds, and nanoseconds. */ |
189 |
long int rel_year; |
relative_time rel; |
|
long int rel_month; |
|
|
long int rel_day; |
|
|
long int rel_hour; |
|
|
long int rel_minutes; |
|
|
long int rel_seconds; |
|
|
long int rel_ns; |
|
190 |
|
|
191 |
/* Presence or counts of nonterminals of various flavors parsed so far. */ |
/* Presence or counts of nonterminals of various flavors parsed so far. */ |
192 |
bool timespec_seen; |
bool timespec_seen; |
223 |
long int intval; |
long int intval; |
224 |
textint textintval; |
textint textintval; |
225 |
struct timespec timespec; |
struct timespec timespec; |
226 |
|
relative_time rel; |
227 |
} |
} |
228 |
|
|
229 |
%token tAGO tDST |
%token tAGO tDST |
230 |
|
|
231 |
%token <intval> tDAY tDAY_UNIT tDAYZONE tHOUR_UNIT tLOCAL_ZONE tMERIDIAN |
%token tYEAR_UNIT tMONTH_UNIT tHOUR_UNIT tMINUTE_UNIT tSEC_UNIT |
232 |
%token <intval> tMINUTE_UNIT tMONTH tMONTH_UNIT tORDINAL |
%token <intval> tDAY_UNIT |
233 |
%token <intval> tSEC_UNIT tYEAR_UNIT tZONE |
|
234 |
|
%token <intval> tDAY tDAYZONE tLOCAL_ZONE tMERIDIAN |
235 |
|
%token <intval> tMONTH tORDINAL tZONE |
236 |
|
|
237 |
%token <textintval> tSNUMBER tUNUMBER |
%token <textintval> tSNUMBER tUNUMBER |
238 |
%token <timespec> tSDECIMAL_NUMBER tUDECIMAL_NUMBER |
%token <timespec> tSDECIMAL_NUMBER tUDECIMAL_NUMBER |
240 |
%type <intval> o_colon_minutes o_merid |
%type <intval> o_colon_minutes o_merid |
241 |
%type <timespec> seconds signed_seconds unsigned_seconds |
%type <timespec> seconds signed_seconds unsigned_seconds |
242 |
|
|
243 |
|
%type <rel> relunit relunit_snumber |
244 |
|
|
245 |
%% |
%% |
246 |
|
|
247 |
spec: |
spec: |
340 |
tZONE |
tZONE |
341 |
{ pc->time_zone = $1; } |
{ pc->time_zone = $1; } |
342 |
| tZONE relunit_snumber |
| tZONE relunit_snumber |
343 |
{ pc->time_zone = $1; pc->rels_seen = true; } |
{ pc->time_zone = $1; |
344 |
|
pc->rel.ns += $2.ns; |
345 |
|
pc->rel.seconds += $2.seconds; |
346 |
|
pc->rel.minutes += $2.minutes; |
347 |
|
pc->rel.hour += $2.hour; |
348 |
|
pc->rel.day += $2.day; |
349 |
|
pc->rel.month += $2.month; |
350 |
|
pc->rel.year += $2.year; |
351 |
|
pc->rels_seen = true; } |
352 |
| tZONE tSNUMBER o_colon_minutes |
| tZONE tSNUMBER o_colon_minutes |
353 |
{ pc->time_zone = $1 + time_zone_hhmm ($2, $3); } |
{ pc->time_zone = $1 + time_zone_hhmm ($2, $3); } |
354 |
| tDAYZONE |
| tDAYZONE |
456 |
rel: |
rel: |
457 |
relunit tAGO |
relunit tAGO |
458 |
{ |
{ |
459 |
pc->rel_ns = -pc->rel_ns; |
pc->rel.ns -= $1.ns; |
460 |
pc->rel_seconds = -pc->rel_seconds; |
pc->rel.seconds -= $1.seconds; |
461 |
pc->rel_minutes = -pc->rel_minutes; |
pc->rel.minutes -= $1.minutes; |
462 |
pc->rel_hour = -pc->rel_hour; |
pc->rel.hour -= $1.hour; |
463 |
pc->rel_day = -pc->rel_day; |
pc->rel.day -= $1.day; |
464 |
pc->rel_month = -pc->rel_month; |
pc->rel.month -= $1.month; |
465 |
pc->rel_year = -pc->rel_year; |
pc->rel.year -= $1.year; |
466 |
} |
} |
467 |
| relunit |
| relunit |
468 |
|
{ |
469 |
|
pc->rel.ns += $1.ns; |
470 |
|
pc->rel.seconds += $1.seconds; |
471 |
|
pc->rel.minutes += $1.minutes; |
472 |
|
pc->rel.hour += $1.hour; |
473 |
|
pc->rel.day += $1.day; |
474 |
|
pc->rel.month += $1.month; |
475 |
|
pc->rel.year += $1.year; |
476 |
|
} |
477 |
; |
; |
478 |
|
|
479 |
relunit: |
relunit: |
480 |
tORDINAL tYEAR_UNIT |
tORDINAL tYEAR_UNIT |
481 |
{ pc->rel_year += $1 * $2; } |
{ $$ = RELATIVE_TIME_0; $$.year = $1; } |
482 |
| tUNUMBER tYEAR_UNIT |
| tUNUMBER tYEAR_UNIT |
483 |
{ pc->rel_year += $1.value * $2; } |
{ $$ = RELATIVE_TIME_0; $$.year = $1.value; } |
484 |
| tYEAR_UNIT |
| tYEAR_UNIT |
485 |
{ pc->rel_year += $1; } |
{ $$ = RELATIVE_TIME_0; $$.year = 1; } |
486 |
| tORDINAL tMONTH_UNIT |
| tORDINAL tMONTH_UNIT |
487 |
{ pc->rel_month += $1 * $2; } |
{ $$ = RELATIVE_TIME_0; $$.month = $1; } |
488 |
| tUNUMBER tMONTH_UNIT |
| tUNUMBER tMONTH_UNIT |
489 |
{ pc->rel_month += $1.value * $2; } |
{ $$ = RELATIVE_TIME_0; $$.month = $1.value; } |
490 |
| tMONTH_UNIT |
| tMONTH_UNIT |
491 |
{ pc->rel_month += $1; } |
{ $$ = RELATIVE_TIME_0; $$.month = 1; } |
492 |
| tORDINAL tDAY_UNIT |
| tORDINAL tDAY_UNIT |
493 |
{ pc->rel_day += $1 * $2; } |
{ $$ = RELATIVE_TIME_0; $$.day = $1 * $2; } |
494 |
| tUNUMBER tDAY_UNIT |
| tUNUMBER tDAY_UNIT |
495 |
{ pc->rel_day += $1.value * $2; } |
{ $$ = RELATIVE_TIME_0; $$.day = $1.value * $2; } |
496 |
| tDAY_UNIT |
| tDAY_UNIT |
497 |
{ pc->rel_day += $1; } |
{ $$ = RELATIVE_TIME_0; $$.day = $1; } |
498 |
| tORDINAL tHOUR_UNIT |
| tORDINAL tHOUR_UNIT |
499 |
{ pc->rel_hour += $1 * $2; } |
{ $$ = RELATIVE_TIME_0; $$.hour = $1; } |
500 |
| tUNUMBER tHOUR_UNIT |
| tUNUMBER tHOUR_UNIT |
501 |
{ pc->rel_hour += $1.value * $2; } |
{ $$ = RELATIVE_TIME_0; $$.hour = $1.value; } |
502 |
| tHOUR_UNIT |
| tHOUR_UNIT |
503 |
{ pc->rel_hour += $1; } |
{ $$ = RELATIVE_TIME_0; $$.hour = 1; } |
504 |
| tORDINAL tMINUTE_UNIT |
| tORDINAL tMINUTE_UNIT |
505 |
{ pc->rel_minutes += $1 * $2; } |
{ $$ = RELATIVE_TIME_0; $$.minutes = $1; } |
506 |
| tUNUMBER tMINUTE_UNIT |
| tUNUMBER tMINUTE_UNIT |
507 |
{ pc->rel_minutes += $1.value * $2; } |
{ $$ = RELATIVE_TIME_0; $$.minutes = $1.value; } |
508 |
| tMINUTE_UNIT |
| tMINUTE_UNIT |
509 |
{ pc->rel_minutes += $1; } |
{ $$ = RELATIVE_TIME_0; $$.minutes = 1; } |
510 |
| tORDINAL tSEC_UNIT |
| tORDINAL tSEC_UNIT |
511 |
{ pc->rel_seconds += $1 * $2; } |
{ $$ = RELATIVE_TIME_0; $$.seconds = $1; } |
512 |
| tUNUMBER tSEC_UNIT |
| tUNUMBER tSEC_UNIT |
513 |
{ pc->rel_seconds += $1.value * $2; } |
{ $$ = RELATIVE_TIME_0; $$.seconds = $1.value; } |
514 |
| tSDECIMAL_NUMBER tSEC_UNIT |
| tSDECIMAL_NUMBER tSEC_UNIT |
515 |
{ pc->rel_seconds += $1.tv_sec * $2; pc->rel_ns += $1.tv_nsec * $2; } |
{ $$ = RELATIVE_TIME_0; $$.seconds = $1.tv_sec; $$.ns = $1.tv_nsec; } |
516 |
| tUDECIMAL_NUMBER tSEC_UNIT |
| tUDECIMAL_NUMBER tSEC_UNIT |
517 |
{ pc->rel_seconds += $1.tv_sec * $2; pc->rel_ns += $1.tv_nsec * $2; } |
{ $$ = RELATIVE_TIME_0; $$.seconds = $1.tv_sec; $$.ns = $1.tv_nsec; } |
518 |
| tSEC_UNIT |
| tSEC_UNIT |
519 |
{ pc->rel_seconds += $1; } |
{ $$ = RELATIVE_TIME_0; $$.seconds = 1; } |
520 |
| relunit_snumber |
| relunit_snumber |
521 |
; |
; |
522 |
|
|
523 |
relunit_snumber: |
relunit_snumber: |
524 |
tSNUMBER tYEAR_UNIT |
tSNUMBER tYEAR_UNIT |
525 |
{ pc->rel_year += $1.value * $2; } |
{ $$ = RELATIVE_TIME_0; $$.year = $1.value; } |
526 |
| tSNUMBER tMONTH_UNIT |
| tSNUMBER tMONTH_UNIT |
527 |
{ pc->rel_month += $1.value * $2; } |
{ $$ = RELATIVE_TIME_0; $$.month = $1.value; } |
528 |
| tSNUMBER tDAY_UNIT |
| tSNUMBER tDAY_UNIT |
529 |
{ pc->rel_day += $1.value * $2; } |
{ $$ = RELATIVE_TIME_0; $$.day = $1.value * $2; } |
530 |
| tSNUMBER tHOUR_UNIT |
| tSNUMBER tHOUR_UNIT |
531 |
{ pc->rel_hour += $1.value * $2; } |
{ $$ = RELATIVE_TIME_0; $$.hour = $1.value; } |
532 |
| tSNUMBER tMINUTE_UNIT |
| tSNUMBER tMINUTE_UNIT |
533 |
{ pc->rel_minutes += $1.value * $2; } |
{ $$ = RELATIVE_TIME_0; $$.minutes = $1.value; } |
534 |
| tSNUMBER tSEC_UNIT |
| tSNUMBER tSEC_UNIT |
535 |
{ pc->rel_seconds += $1.value * $2; } |
{ $$ = RELATIVE_TIME_0; $$.seconds = $1.value; } |
536 |
; |
; |
537 |
|
|
538 |
seconds: signed_seconds | unsigned_seconds; |
seconds: signed_seconds | unsigned_seconds; |
1250 |
tm.tm_isdst = tmp->tm_isdst; |
tm.tm_isdst = tmp->tm_isdst; |
1251 |
|
|
1252 |
pc.meridian = MER24; |
pc.meridian = MER24; |
1253 |
pc.rel_ns = 0; |
pc.rel = RELATIVE_TIME_0; |
|
pc.rel_seconds = 0; |
|
|
pc.rel_minutes = 0; |
|
|
pc.rel_hour = 0; |
|
|
pc.rel_day = 0; |
|
|
pc.rel_month = 0; |
|
|
pc.rel_year = 0; |
|
1254 |
pc.timespec_seen = false; |
pc.timespec_seen = false; |
1255 |
pc.rels_seen = false; |
pc.rels_seen = false; |
1256 |
pc.dates_seen = 0; |
pc.dates_seen = 0; |
1347 |
} |
} |
1348 |
|
|
1349 |
/* Let mktime deduce tm_isdst if we have an absolute time stamp. */ |
/* Let mktime deduce tm_isdst if we have an absolute time stamp. */ |
1350 |
if (!pc.rels_seen) |
if (pc.dates_seen | pc.days_seen | pc.times_seen) |
1351 |
tm.tm_isdst = -1; |
tm.tm_isdst = -1; |
1352 |
|
|
1353 |
/* But if the input explicitly specifies local time with or without |
/* But if the input explicitly specifies local time with or without |
1425 |
} |
} |
1426 |
|
|
1427 |
/* Add relative date. */ |
/* Add relative date. */ |
1428 |
if (pc.rel_year | pc.rel_month | pc.rel_day) |
if (pc.rel.year | pc.rel.month | pc.rel.day) |
1429 |
{ |
{ |
1430 |
int year = tm.tm_year + pc.rel_year; |
int year = tm.tm_year + pc.rel.year; |
1431 |
int month = tm.tm_mon + pc.rel_month; |
int month = tm.tm_mon + pc.rel.month; |
1432 |
int day = tm.tm_mday + pc.rel_day; |
int day = tm.tm_mday + pc.rel.day; |
1433 |
if (((year < tm.tm_year) ^ (pc.rel_year < 0)) |
if (((year < tm.tm_year) ^ (pc.rel.year < 0)) |
1434 |
| ((month < tm.tm_mon) ^ (pc.rel_month < 0)) |
| ((month < tm.tm_mon) ^ (pc.rel.month < 0)) |
1435 |
| ((day < tm.tm_mday) ^ (pc.rel_day < 0))) |
| ((day < tm.tm_mday) ^ (pc.rel.day < 0))) |
1436 |
goto fail; |
goto fail; |
1437 |
tm.tm_year = year; |
tm.tm_year = year; |
1438 |
tm.tm_mon = month; |
tm.tm_mon = month; |
1450 |
must be applied before relative times, and if mktime is applied |
must be applied before relative times, and if mktime is applied |
1451 |
again the time zone will be lost. */ |
again the time zone will be lost. */ |
1452 |
{ |
{ |
1453 |
long int sum_ns = pc.seconds.tv_nsec + pc.rel_ns; |
long int sum_ns = pc.seconds.tv_nsec + pc.rel.ns; |
1454 |
long int normalized_ns = (sum_ns % BILLION + BILLION) % BILLION; |
long int normalized_ns = (sum_ns % BILLION + BILLION) % BILLION; |
1455 |
time_t t0 = Start; |
time_t t0 = Start; |
1456 |
long int d1 = 60 * 60 * pc.rel_hour; |
long int d1 = 60 * 60 * pc.rel.hour; |
1457 |
time_t t1 = t0 + d1; |
time_t t1 = t0 + d1; |
1458 |
long int d2 = 60 * pc.rel_minutes; |
long int d2 = 60 * pc.rel.minutes; |
1459 |
time_t t2 = t1 + d2; |
time_t t2 = t1 + d2; |
1460 |
long int d3 = pc.rel_seconds; |
long int d3 = pc.rel.seconds; |
1461 |
time_t t3 = t2 + d3; |
time_t t3 = t2 + d3; |
1462 |
long int d4 = (sum_ns - normalized_ns) / BILLION; |
long int d4 = (sum_ns - normalized_ns) / BILLION; |
1463 |
time_t t4 = t3 + d4; |
time_t t4 = t3 + d4; |
1464 |
|
|
1465 |
if ((d1 / (60 * 60) ^ pc.rel_hour) |
if ((d1 / (60 * 60) ^ pc.rel.hour) |
1466 |
| (d2 / 60 ^ pc.rel_minutes) |
| (d2 / 60 ^ pc.rel.minutes) |
1467 |
| ((t1 < t0) ^ (d1 < 0)) |
| ((t1 < t0) ^ (d1 < 0)) |
1468 |
| ((t2 < t1) ^ (d2 < 0)) |
| ((t2 < t1) ^ (d2 < 0)) |
1469 |
| ((t3 < t2) ^ (d3 < 0)) |
| ((t3 < t2) ^ (d3 < 0)) |