#include "logger.h"
#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include <ctype.h>
#include <sys/time.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#define tAGO 257
#define tDAY 258
#define tDAY_UNIT 259
#define tDAYZONE 260
#define tDST 261
#define tHOUR_UNIT 262
#define tID 263
#define tMERIDIAN 264
#define tMINUTE_UNIT 265
#define tMONTH 266
#define tMONTH_UNIT 267
#define tSEC_UNIT 268
#define tSNUMBER 269
#define tUNUMBER 270
#define tYEAR_UNIT 271
#define tZONE 272
#define ISSPACE(c) (isascii (c) && isspace (c))
#define ISALPHA(c) (isascii (c) && isalpha (c))
#define ISUPPER(c) (isascii (c) && isupper (c))
#define ISDIGIT_LOCALE(c) (isascii (c) && isdigit (c))
#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) #define EPOCH 1970
#define HOUR(x) ((x) * 60)
#define MAX_BUFF_LEN 128
#define PARSE_DATE_FINAL 62
#define PARSE_DATE_FLAG -32768
#define PARSE_DATE_NTBASE 22
#define PARSE_DATE_TRANSLATE(x) ((unsigned)(x) <= 272 ? parse_date_translate[x] : 32)
#define PARSE_DATE_LAST 52
#define PARSE_DATE_TERROR 1
#define PARSE_DATE_ERRCODE 256
#define PARSE_DATE_INITDEPTH 200
#define PARSE_DATE_MAXDEPTH 10000
#define TM_YEAR_ORIGIN 1900
#define PARSE_DATE_BACKUP(token, value) \
do \
if (parse_date_char == -2 && parse_date_len == 1) \
{ parse_date_char = (token), parse_date_lval = (value); \
parse_date_char1 = PARSE_DATE_TRANSLATE (parse_date_char); \
parse_date_vsp--, parse_date_ssp--; \
goto parse_date_backup; \
} \
else \
{ parse_date_error ("syntax error: cannot back up"); goto parse_date_errlab1; } \
while (0)
typedef struct {
const char *name;
int type;
int value;
} TABLE;
typedef enum {
MERam, MERpm, MER24
} MERIDIAN;
typedef union {
int Number;
MERIDIAN Meridian;
} PARSE_DATE_STYPE;
int parse_date ();
static int parse_date_lex ();
static int parse_date_error ();
static const char *parse_date_Input;
static int parse_date_DayOrdinal;
static int parse_date_DayNumber;
static int parse_date_HaveDate;
static int parse_date_HaveDay;
static int parse_date_HaveRel;
static int parse_date_HaveTime;
static int parse_date_HaveZone;
static int parse_date_Timezone;
static int parse_date_Day;
static int parse_date_Hour;
static int parse_date_Minutes;
static int parse_date_Month;
static int parse_date_Seconds;
static int parse_date_Year;
static MERIDIAN parse_date_Meridian;
static int parse_date_RelDay;
static int parse_date_RelHour;
static int parse_date_RelMinutes;
static int parse_date_RelMonth;
static int parse_date_RelSeconds;
static int parse_date_RelYear;
int parse_date_char;
PARSE_DATE_STYPE parse_date_lval;
int parse_date_nerrs;
static const char parse_date_translate[] = { 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 20, 2, 2, 21, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 19, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18
};
static const char *const parse_date_tname[] =
{ "$", "error", "$undefined.", "tAGO", "tDAY",
"tDAY_UNIT", "tDAYZONE", "tDST", "tHOUR_UNIT", "tID", "tMERIDIAN",
"tMINUTE_UNIT",
"tMONTH", "tMONTH_UNIT", "tSEC_UNIT", "tSNUMBER", "tUNUMBER", "tYEAR_UNIT",
"tZONE",
"':'", "','", "'/'", "spec", "item", "time", "zone", "day", "date", "rel",
"relunit", "number",
"o_merid", NULL
};
static const short parse_date_r1[] = { 0,
22, 22, 23, 23, 23, 23, 23, 23, 24, 24,
24, 24, 24, 25, 25, 25, 26, 26, 26, 27,
27, 27, 27, 27, 27, 27, 27, 27, 28, 28,
29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
29, 29, 29, 29, 29, 29, 29, 29, 30, 31,
31
};
static const short parse_date_r2[] = { 0,
0, 2, 1, 1, 1, 1, 1, 1, 2, 4,
4, 6, 6, 1, 1, 2, 1, 2, 2, 3,
5, 3, 3, 3, 2, 4, 2, 3, 2, 1,
2, 2, 1, 2, 2, 1, 2, 2, 1, 2,
2, 1, 2, 2, 1, 2, 2, 1, 1, 0,
1
};
static const short parse_date_defact[] = { 1,
0, 17, 39, 15, 42, 45, 0, 36, 48, 0,
49, 33, 14, 2, 3, 4, 6, 5, 7, 30,
8, 18, 25, 38, 41, 44, 35, 47, 32, 19,
37, 40, 9, 43, 27, 34, 46, 0, 31, 0,
0, 16, 29, 24, 0, 23, 28, 22, 50, 20,
26, 51, 11, 0, 10, 0, 50, 21, 13, 12,
0, 0
};
static const short parse_date_defgoto[] = { 1,
14, 15, 16, 17, 18, 19, 20, 21, 55
};
static const short parse_date_pact[] = { -32768,
0, -19, -32768, -32768, -32768, -32768, -13, -32768, -32768, 30,
15, -32768, 14, -32768, -32768, -32768, -32768, -32768, -32768, 19,
-32768, -32768, 29, -32768, -32768, -32768, -32768, -32768, -32768, -32768,
-32768, -32768, -32768, -32768, -6, -32768, -32768, 9, -32768, 17,
23, -32768, -32768, -32768, 24, -32768, -32768, -32768, 27, 10,
-32768, -32768, -32768, 32, -32768, 34, -8, -32768, -32768, -32768,
51, -32768
};
static const short parse_date_pgoto[] = { -32768,
-32768, -32768, -32768, -32768, -32768, -32768, -32768, -32768, -5
};
static const short parse_date_table[] = { 61,
22, 52, 23, 2, 3, 4, 59, 5, 46, 47,
6, 7, 8, 9, 10, 11, 12, 13, 30, 31,
42, 43, 32, 48, 33, 34, 35, 36, 37, 38,
56, 39, 49, 40, 24, 41, 52, 25, 50, 51,
26, 53, 27, 28, 44, 54, 29, 57, 45, 58,
62, 60
};
static const short parse_date_check[] = { 0,
20, 10, 16, 4, 5, 6, 15, 8, 15, 16,
11, 12, 13, 14, 15, 16, 17, 18, 4, 5,
7, 3, 8, 15, 10, 11, 12, 13, 14, 15,
21, 17, 16, 19, 5, 21, 10, 8, 16, 16,
11, 15, 13, 14, 16, 19, 17, 16, 20, 16,
0, 57
};
int
parse_date ()
{
register int parse_date_state;
register int parse_date_n;
register short *parse_date_ssp;
register PARSE_DATE_STYPE *parse_date_vsp;
int parse_date_errstatus;
int parse_date_char1 = 0;
short parse_date_ssa[PARSE_DATE_INITDEPTH];
PARSE_DATE_STYPE parse_date_vsa[PARSE_DATE_INITDEPTH];
short *parse_date_ss = parse_date_ssa;
PARSE_DATE_STYPE *parse_date_vs = parse_date_vsa;
int parse_date_stacksize = PARSE_DATE_INITDEPTH;
int parse_date_free_stacks = 0;
PARSE_DATE_STYPE parse_date_val; /* the variable used to return */
/* semantic values from the action */
/* routines */
int parse_date_len;
parse_date_state = 0;
parse_date_errstatus = 0;
parse_date_nerrs = 0;
parse_date_char = -2; /* Cause a token to be read. */
/* Initialize stack pointers.
Waste one element of value and location stack
so that they stay on the same level as the state stack.
The wasted elements are never initialized. */
parse_date_ssp = parse_date_ss - 1;
parse_date_vsp = parse_date_vs;
parse_date_constructstate:
*++parse_date_ssp = parse_date_state;
if (parse_date_ssp >= parse_date_ss + parse_date_stacksize - 1) {
PARSE_DATE_STYPE *parse_date_vs1 = parse_date_vs;
short *parse_date_ss1 = parse_date_ss;
/* Get the current used size of the three stacks, in elements. */
int size = parse_date_ssp - parse_date_ss + 1;
if (parse_date_stacksize >= PARSE_DATE_MAXDEPTH) {
parse_date_error ("parser stack overflow");
if (parse_date_free_stacks) {
free (parse_date_ss);
free (parse_date_vs);
}
return 2;
}
parse_date_stacksize *= 2;
if (parse_date_stacksize > PARSE_DATE_MAXDEPTH)
parse_date_stacksize = PARSE_DATE_MAXDEPTH;
parse_date_ss =
(short *) malloc (parse_date_stacksize * sizeof (*parse_date_ssp));
//__builtin_memcpy ((char *) parse_date_ss, (char *) parse_date_ss1,
// size * (unsigned int) sizeof (*parse_date_ssp));
memcpy ((char *) parse_date_ss, (char *) parse_date_ss1,
size * (unsigned int) sizeof (*parse_date_ssp));
parse_date_vs =
(PARSE_DATE_STYPE *) malloc (parse_date_stacksize *
sizeof (*parse_date_vsp));
//__builtin_memcpy ((char *) parse_date_vs, (char *) parse_date_vs1,
// size * (unsigned int) sizeof (*parse_date_vsp));
memcpy ((char *) parse_date_vs, (char *) parse_date_vs1,
size * (unsigned int) sizeof (*parse_date_vsp));
parse_date_ssp = parse_date_ss + size - 1;
parse_date_vsp = parse_date_vs + size - 1;
if (parse_date_ssp >= parse_date_ss + parse_date_stacksize - 1)
goto parse_date_abortlab;
}
goto parse_date_backup;
parse_date_backup:
parse_date_n = parse_date_pact[parse_date_state];
if (parse_date_n == PARSE_DATE_FLAG)
goto parse_date_default;
if (parse_date_char == -2) {
parse_date_char = parse_date_lex ();
}
if (parse_date_char <= 0) { /* This means end of input. */
parse_date_char1 = 0;
parse_date_char = 0; /* Don't call parse_date_lex() any more */
}
else {
parse_date_char1 = PARSE_DATE_TRANSLATE (parse_date_char);
}
parse_date_n += parse_date_char1;
if (parse_date_n < 0 || parse_date_n > PARSE_DATE_LAST
|| parse_date_check[parse_date_n] != parse_date_char1)
goto parse_date_default;
parse_date_n = parse_date_table[parse_date_n];
if (parse_date_n < 0) {
if (parse_date_n == PARSE_DATE_FLAG)
goto parse_date_errlab;
parse_date_n = -parse_date_n;
goto parse_date_reduce;
}
else if (parse_date_n == 0)
goto parse_date_errlab;
if (parse_date_n == PARSE_DATE_FINAL)
goto parse_date_acceptlab;
if (parse_date_char != 0)
parse_date_char = -2;
*++parse_date_vsp = parse_date_lval;
/* count tokens shifted since error; after three, turn off error status. */
if (parse_date_errstatus)
parse_date_errstatus--;
parse_date_state = parse_date_n;
goto parse_date_constructstate;
/* Do the default action for the current state. */
parse_date_default:
parse_date_n = parse_date_defact[parse_date_state];
if (parse_date_n == 0)
goto parse_date_errlab;
/* Do a reduction. parse_date_n is the number of a rule to reduce with. */
parse_date_reduce:
parse_date_len = parse_date_r2[parse_date_n];
if (parse_date_len > 0)
parse_date_val = parse_date_vsp[1 - parse_date_len]; /* implement default value of the action */
switch (parse_date_n) {
case 3:
{
parse_date_HaveTime++;
;
break;
}
case 4:
{
parse_date_HaveZone++;
;
break;
}
case 5:
{
parse_date_HaveDate++;
;
break;
}
case 6:
{
parse_date_HaveDay++;
;
break;
}
case 7:
{
parse_date_HaveRel++;
;
break;
}
case 9:
{
parse_date_Hour = parse_date_vsp[-1].Number;
parse_date_Minutes = 0;
parse_date_Seconds = 0;
parse_date_Meridian = parse_date_vsp[0].Meridian;
;
break;
}
case 10:
{
parse_date_Hour = parse_date_vsp[-3].Number;
parse_date_Minutes = parse_date_vsp[-1].Number;
parse_date_Seconds = 0;
parse_date_Meridian = parse_date_vsp[0].Meridian;
;
break;
}
case 11:
{
parse_date_Hour = parse_date_vsp[-3].Number;
parse_date_Minutes = parse_date_vsp[-1].Number;
parse_date_Meridian = MER24;
parse_date_HaveZone++;
parse_date_Timezone = (parse_date_vsp[0].Number < 0
? -parse_date_vsp[0].Number % 100 +
(-parse_date_vsp[0].Number / 100) *
60 : -(parse_date_vsp[0].Number % 100 +
(parse_date_vsp[0].Number / 100) * 60));
;
break;
}
case 12:
{
parse_date_Hour = parse_date_vsp[-5].Number;
parse_date_Minutes = parse_date_vsp[-3].Number;
parse_date_Seconds = parse_date_vsp[-1].Number;
parse_date_Meridian = parse_date_vsp[0].Meridian;
;
break;
}
case 13:
{
parse_date_Hour = parse_date_vsp[-5].Number;
parse_date_Minutes = parse_date_vsp[-3].Number;
parse_date_Seconds = parse_date_vsp[-1].Number;
parse_date_Meridian = MER24;
parse_date_HaveZone++;
parse_date_Timezone = (parse_date_vsp[0].Number < 0
? -parse_date_vsp[0].Number % 100 +
(-parse_date_vsp[0].Number / 100) *
60 : -(parse_date_vsp[0].Number % 100 +
(parse_date_vsp[0].Number / 100) * 60));
;
break;
}
case 14:
{
parse_date_Timezone = parse_date_vsp[0].Number;
;
break;
}
case 15:
{
parse_date_Timezone = parse_date_vsp[0].Number - 60;
;
break;
}
case 16:
{
parse_date_Timezone = parse_date_vsp[-1].Number - 60;
;
break;
}
case 17:
{
parse_date_DayOrdinal = 1;
parse_date_DayNumber = parse_date_vsp[0].Number;
;
break;
}
case 18:
{
parse_date_DayOrdinal = 1;
parse_date_DayNumber = parse_date_vsp[-1].Number;
;
break;
}
case 19:
{
parse_date_DayOrdinal = parse_date_vsp[-1].Number;
parse_date_DayNumber = parse_date_vsp[0].Number;
;
break;
}
case 20:
{
parse_date_Month = parse_date_vsp[-2].Number;
parse_date_Day = parse_date_vsp[0].Number;
;
break;
}
case 21:
{
/* Interpret as PARSE_DATE_PARSE_DATE_/MM/DD if $1 >= 1000, otherwise as MM/DD/PARSE_DATE_.
The goal in recognizing PARSE_DATE_PARSE_DATE_/MM/DD is solely to support legacy
machine-generated dates like those in an RCS log listing. If
you want portability, use the ISO 8601 format. */
if (parse_date_vsp[-4].Number >= 1000) {
parse_date_Year = parse_date_vsp[-4].Number;
parse_date_Month = parse_date_vsp[-2].Number;
parse_date_Day = parse_date_vsp[0].Number;
}
else {
parse_date_Month = parse_date_vsp[-4].Number;
parse_date_Day = parse_date_vsp[-2].Number;
parse_date_Year = parse_date_vsp[0].Number;
}
;
break;
}
case 22:
{
/* ISO 8601 format. parse_date_date_-mm-dd. */
parse_date_Year = parse_date_vsp[-2].Number;
parse_date_Month = -parse_date_vsp[-1].Number;
parse_date_Day = -parse_date_vsp[0].Number;
;
break;
}
case 23:
{
/* e.g. 17-JUN-1992. */
parse_date_Day = parse_date_vsp[-2].Number;
parse_date_Month = parse_date_vsp[-1].Number;
parse_date_Year = -parse_date_vsp[0].Number;
;
break;
}
case 24:
{
parse_date_Month = parse_date_vsp[-2].Number;
parse_date_Day = parse_date_vsp[-1].Number;
parse_date_Year = parse_date_vsp[0].Number;
;
break;
}
case 25:
{
parse_date_Month = parse_date_vsp[-1].Number;
parse_date_Day = parse_date_vsp[0].Number;
;
break;
}
case 26:
{
parse_date_Month = parse_date_vsp[-3].Number;
parse_date_Day = parse_date_vsp[-2].Number;
parse_date_Year = parse_date_vsp[0].Number;
;
break;
}
case 27:
{
parse_date_Month = parse_date_vsp[0].Number;
parse_date_Day = parse_date_vsp[-1].Number;
;
break;
}
case 28:
{
parse_date_Month = parse_date_vsp[-1].Number;
parse_date_Day = parse_date_vsp[-2].Number;
parse_date_Year = parse_date_vsp[0].Number;
;
break;
}
case 29:
{
parse_date_RelSeconds = -parse_date_RelSeconds;
parse_date_RelMinutes = -parse_date_RelMinutes;
parse_date_RelHour = -parse_date_RelHour;
parse_date_RelDay = -parse_date_RelDay;
parse_date_RelMonth = -parse_date_RelMonth;
parse_date_RelYear = -parse_date_RelYear;
;
break;
}
case 31:
{
parse_date_RelYear +=
parse_date_vsp[-1].Number * parse_date_vsp[0].Number;
;
break;
}
case 32:
{
parse_date_RelYear +=
parse_date_vsp[-1].Number * parse_date_vsp[0].Number;
;
break;
}
case 33:
{
parse_date_RelYear += parse_date_vsp[0].Number;
;
break;
}
case 34:
{
parse_date_RelMonth +=
parse_date_vsp[-1].Number * parse_date_vsp[0].Number;
;
break;
}
case 35:
{
parse_date_RelMonth +=
parse_date_vsp[-1].Number * parse_date_vsp[0].Number;
;
break;
}
case 36:
{
parse_date_RelMonth += parse_date_vsp[0].Number;
;
break;
}
case 37:
{
parse_date_RelDay +=
parse_date_vsp[-1].Number * parse_date_vsp[0].Number;
;
break;
}
case 38:
{
parse_date_RelDay +=
parse_date_vsp[-1].Number * parse_date_vsp[0].Number;
;
break;
}
case 39:
{
parse_date_RelDay += parse_date_vsp[0].Number;
;
break;
}
case 40:
{
parse_date_RelHour +=
parse_date_vsp[-1].Number * parse_date_vsp[0].Number;
;
break;
}
case 41:
{
parse_date_RelHour +=
parse_date_vsp[-1].Number * parse_date_vsp[0].Number;
;
break;
}
case 42:
{
parse_date_RelHour += parse_date_vsp[0].Number;
;
break;
}
case 43:
{
parse_date_RelMinutes +=
parse_date_vsp[-1].Number * parse_date_vsp[0].Number;
;
break;
}
case 44:
{
parse_date_RelMinutes +=
parse_date_vsp[-1].Number * parse_date_vsp[0].Number;
;
break;
}
case 45:
{
parse_date_RelMinutes += parse_date_vsp[0].Number;
;
break;
}
case 46:
{
parse_date_RelSeconds +=
parse_date_vsp[-1].Number * parse_date_vsp[0].Number;
;
break;
}
case 47:
{
parse_date_RelSeconds +=
parse_date_vsp[-1].Number * parse_date_vsp[0].Number;
;
break;
}
case 48:
{
parse_date_RelSeconds += parse_date_vsp[0].Number;
;
break;
}
case 49:
{
if (parse_date_HaveTime && parse_date_HaveDate && !parse_date_HaveRel)
parse_date_Year = parse_date_vsp[0].Number;
else {
if (parse_date_vsp[0].Number > 10000) {
parse_date_HaveDate++;
parse_date_Day = (parse_date_vsp[0].Number) % 100;
parse_date_Month = (parse_date_vsp[0].Number / 100) % 100;
parse_date_Year = parse_date_vsp[0].Number / 10000;
}
else {
parse_date_HaveTime++;
if (parse_date_vsp[0].Number < 100) {
parse_date_Hour = parse_date_vsp[0].Number;
parse_date_Minutes = 0;
}
else {
parse_date_Hour = parse_date_vsp[0].Number / 100;
parse_date_Minutes = parse_date_vsp[0].Number % 100;
}
parse_date_Seconds = 0;
parse_date_Meridian = MER24;
}
}
;
break;
}
case 50:
{
parse_date_val.Meridian = MER24;
;
break;
}
case 51:
{
parse_date_val.Meridian = parse_date_vsp[0].Meridian;
;
break;
}
}
/* the action file gets copied in in place of this dollarsign */
parse_date_vsp -= parse_date_len;
parse_date_ssp -= parse_date_len;
*++parse_date_vsp = parse_date_val;
/* Now "shift" the result of the reduction.
Determine what state that goes to,
based on the state we popped back to
and the rule number reduced by. */
parse_date_n = parse_date_r1[parse_date_n];
parse_date_state =
parse_date_pgoto[parse_date_n - PARSE_DATE_NTBASE] + *parse_date_ssp;
if (parse_date_state >= 0 && parse_date_state <= PARSE_DATE_LAST
&& parse_date_check[parse_date_state] == *parse_date_ssp)
parse_date_state = parse_date_table[parse_date_state];
else
parse_date_state = parse_date_defgoto[parse_date_n - PARSE_DATE_NTBASE];
goto parse_date_constructstate;
parse_date_errlab: /* here on detecting error */
if (!parse_date_errstatus)
/* If not already recovering from an error, report this error. */
{
++parse_date_nerrs;
parse_date_error ("parse error");
}
goto parse_date_errlab1;
parse_date_errlab1: /* here on error raised explicitly by an action */
if (parse_date_errstatus == 3) {
/* if just tried and failed to reuse lookahead token after an error, discard it. */
/* return failure if at end of input */
if (parse_date_char == 0)
goto parse_date_abortlab;
parse_date_char = -2;
}
/* Else will try to reuse lookahead token
after shifting the error token. */
parse_date_errstatus = 3; /* Each real token shifted decrements this */
goto parse_date_errhandle;
parse_date_errdefault: /* current state does not do anything special for the error token. */
parse_date_errpop: /* pop the current state because it cannot handle the error token */
if (parse_date_ssp == parse_date_ss)
goto parse_date_abortlab;
parse_date_vsp--;
parse_date_state = *--parse_date_ssp;
parse_date_errhandle:
parse_date_n = parse_date_pact[parse_date_state];
if (parse_date_n == PARSE_DATE_FLAG)
goto parse_date_errdefault;
parse_date_n += PARSE_DATE_TERROR;
if (parse_date_n < 0 || parse_date_n > PARSE_DATE_LAST
|| parse_date_check[parse_date_n] != PARSE_DATE_TERROR)
goto parse_date_errdefault;
parse_date_n = parse_date_table[parse_date_n];
if (parse_date_n < 0) {
if (parse_date_n == PARSE_DATE_FLAG)
goto parse_date_errpop;
parse_date_n = -parse_date_n;
goto parse_date_reduce;
}
else if (parse_date_n == 0)
goto parse_date_errpop;
if (parse_date_n == PARSE_DATE_FINAL)
goto parse_date_acceptlab;
*++parse_date_vsp = parse_date_lval;
parse_date_state = parse_date_n;
goto parse_date_constructstate;
parse_date_acceptlab:
/* goto parse_date_acceptlab comes here. */
if (parse_date_free_stacks) {
free (parse_date_ss);
free (parse_date_vs);
}
return 0;
parse_date_abortlab:
/* goto parse_date_abortlab comes here. */
if (parse_date_free_stacks) {
free (parse_date_ss);
free (parse_date_vs);
}
return 1;
}
time_t get_date (char *p, time_t * now);
/* Month and day table. */
static TABLE const MonthDayTable[] = {
{"january", tMONTH, 1},
{"february", tMONTH, 2},
{"march", tMONTH, 3},
{"april", tMONTH, 4},
{"may", tMONTH, 5},
{"june", tMONTH, 6},
{"july", tMONTH, 7},
{"august", tMONTH, 8},
{"september", tMONTH, 9},
{"sept", tMONTH, 9},
{"october", tMONTH, 10},
{"november", tMONTH, 11},
{"december", tMONTH, 12},
{"sunday", tDAY, 0},
{"monday", tDAY, 1},
{"tuesday", tDAY, 2},
{"tues", tDAY, 2},
{"wednesday", tDAY, 3},
{"wednes", tDAY, 3},
{"thursday", tDAY, 4},
{"thur", tDAY, 4},
{"thurs", tDAY, 4},
{"friday", tDAY, 5},
{"saturday", tDAY, 6},
{NULL, 0, 0}
};
/* Time units table. */
static TABLE const UnitsTable[] = {
{"year", tYEAR_UNIT, 1},
{"month", tMONTH_UNIT, 1},
{"fortnight", tDAY_UNIT, 14},
{"week", tDAY_UNIT, 7},
{"day", tDAY_UNIT, 1},
{"hour", tHOUR_UNIT, 1},
{"minute", tMINUTE_UNIT, 1},
{"min", tMINUTE_UNIT, 1},
{"second", tSEC_UNIT, 1},
{"sec", tSEC_UNIT, 1},
{NULL, 0, 0}
};
/* Assorted relative-time words. */
static TABLE const OtherTable[] = {
{"tomorrow", tDAY_UNIT, 1},
{"yesterday", tDAY_UNIT, -1},
{"today", tDAY_UNIT, 0},
{"now", tDAY_UNIT, 0},
{"last", tUNUMBER, -1},
{"this", tMINUTE_UNIT, 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},
{"ago", tAGO, 1},
{NULL, 0, 0}
};
/* The timezone table. */
static TABLE const TimezoneTable[] = {
{"gmt", tZONE, HOUR (0)}, /* Greenwich Mean */
{"ut", tZONE, HOUR (0)}, /* Universal (Coordinated) */
{"utc", tZONE, HOUR (0)},
{"wet", tZONE, HOUR (0)}, /* Western European */
{"bst", tDAYZONE, HOUR (0)}, /* British Summer */
{"wat", tZONE, HOUR (1)}, /* West Africa */
{"at", tZONE, HOUR (2)}, /* Azores */
{"ast", tZONE, HOUR (4)}, /* Atlantic Standard */
{"adt", tDAYZONE, HOUR (4)}, /* Atlantic Daylight */
{"est", tZONE, HOUR (5)}, /* Eastern Standard */
{"edt", tDAYZONE, HOUR (5)}, /* Eastern Daylight */
{"cst", tZONE, HOUR (6)}, /* Central Standard */
{"cdt", tDAYZONE, HOUR (6)}, /* Central Daylight */
{"mst", tZONE, HOUR (7)}, /* Mountain Standard */
{"mdt", tDAYZONE, HOUR (7)}, /* Mountain Daylight */
{"pst", tZONE, HOUR (8)}, /* Pacific Standard */
{"pdt", tDAYZONE, HOUR (8)}, /* Pacific Daylight */
{"yst", tZONE, HOUR (9)}, /* Yukon Standard */
{"ydt", tDAYZONE, HOUR (9)}, /* Yukon Daylight */
{"hst", tZONE, HOUR (10)}, /* Hawaii Standard */
{"hdt", tDAYZONE, HOUR (10)}, /* Hawaii Daylight */
{"cat", tZONE, HOUR (10)}, /* Central Alaska */
{"akst", tZONE, HOUR (10)}, /* Alaska Standard */
{"akdt", tZONE, HOUR (10)}, /* Alaska Daylight */
{"ahst", tZONE, HOUR (10)}, /* Alaska-Hawaii Standard */
{"nt", tZONE, HOUR (11)}, /* Nome */
{"idlw", tZONE, HOUR (12)}, /* International Date Line West */
{"cet", tZONE, -HOUR (1)}, /* Central European */
{"met", tZONE, -HOUR (1)}, /* Middle European */
{"mewt", tZONE, -HOUR (1)}, /* Middle European Winter */
{"mest", tDAYZONE, -HOUR (1)}, /* Middle European Summer */
{"mesz", tDAYZONE, -HOUR (1)}, /* Middle European Summer */
{"swt", tZONE, -HOUR (1)}, /* Swedish Winter */
{"sst", tDAYZONE, -HOUR (1)}, /* Swedish Summer */
{"fwt", tZONE, -HOUR (1)}, /* French Winter */
{"fst", tDAYZONE, -HOUR (1)}, /* French Summer */
{"eet", tZONE, -HOUR (2)}, /* Eastern Europe, USSR Zone 1 */
{"bt", tZONE, -HOUR (3)}, /* Baghdad, USSR Zone 2 */
{"zp4", tZONE, -HOUR (4)}, /* USSR Zone 3 */
{"zp5", tZONE, -HOUR (5)}, /* USSR Zone 4 */
{"zp6", tZONE, -HOUR (6)}, /* USSR Zone 5 */
{"wast", tZONE, -HOUR (7)}, /* West Australian Standard */
{"wadt", tDAYZONE, -HOUR (7)}, /* West Australian Daylight */
{"cct", tZONE, -HOUR (8)}, /* China Coast, USSR Zone 7 */
{"jst", tZONE, -HOUR (9)}, /* Japan Standard, USSR Zone 8 */
{"east", tZONE, -HOUR (10)}, /* Eastern Australian Standard */
{"eadt", tDAYZONE, -HOUR (10)}, /* Eastern Australian Daylight */
{"gst", tZONE, -HOUR (10)}, /* Guam Standard, USSR Zone 9 */
{"nzt", tZONE, -HOUR (12)}, /* New Zealand */
{"nzst", tZONE, -HOUR (12)}, /* New Zealand Standard */
{"nzdt", tDAYZONE, -HOUR (12)}, /* New Zealand Daylight */
{"idle", tZONE, -HOUR (12)}, /* International Date Line East */
{NULL, 0, 0}
};
/* Military timezone table. */
static TABLE const MilitaryTable[] = {
{"a", tZONE, HOUR (1)},
{"b", tZONE, HOUR (2)},
{"c", tZONE, HOUR (3)},
{"d", tZONE, HOUR (4)},
{"e", tZONE, HOUR (5)},
{"f", tZONE, HOUR (6)},
{"g", tZONE, HOUR (7)},
{"h", tZONE, HOUR (8)},
{"i", tZONE, HOUR (9)},
{"k", tZONE, HOUR (10)},
{"l", tZONE, HOUR (11)},
{"m", tZONE, HOUR (12)},
{"n", tZONE, HOUR (-1)},
{"o", tZONE, HOUR (-2)},
{"p", tZONE, HOUR (-3)},
{"q", tZONE, HOUR (-4)},
{"r", tZONE, HOUR (-5)},
{"s", tZONE, HOUR (-6)},
{"t", tZONE, HOUR (-7)},
{"u", tZONE, HOUR (-8)},
{"v", tZONE, HOUR (-9)},
{"w", tZONE, HOUR (-10)},
{"x", tZONE, HOUR (-11)},
{"y", tZONE, HOUR (-12)},
{"z", tZONE, HOUR (0)},
{NULL, 0, 0}
};
static int parse_date_error (char *s) {
s = NULL;
return 0;
}
static int ToHour (int Hours, MERIDIAN Meridian) {
switch (Meridian) {
case MER24:
if (Hours < 0 || Hours > 23)
return -1;
return Hours;
case MERam:
if (Hours < 1 || Hours > 12)
return -1;
if (Hours == 12)
Hours = 0;
return Hours;
case MERpm:
if (Hours < 1 || Hours > 12)
return -1;
if (Hours == 12)
Hours = 0;
return Hours + 12;
default:
abort ();
}
return -1;
}
static int ToYear (int Year) {
if (Year < 0)
Year = -Year;
/* XPG4 suggests that years 00-68 map to 2000-2068, and
years 69-99 map to 1969-1999. */
if (Year < 69)
Year += 2000;
else if (Year < 100)
Year += 1900;
return Year;
}
static int LookupWord (char *buff) {
register char *p;
register char *q;
register const TABLE *tp;
int i;
int abbrev;
/* Make it lowercase. */
for (p = buff; *p; p++)
if (ISUPPER ((unsigned char) *p))
*p = tolower (*p);
if (strcmp (buff, "am") == 0 || strcmp (buff, "a.m.") == 0) {
parse_date_lval.Meridian = MERam;
return tMERIDIAN;
}
if (strcmp (buff, "pm") == 0 || strcmp (buff, "p.m.") == 0) {
parse_date_lval.Meridian = MERpm;
return tMERIDIAN;
}
/* See if we have an abbreviation for a month. */
if (strlen (buff) == 3)
abbrev = 1;
else if (strlen (buff) == 4 && buff[3] == '.') {
abbrev = 1;
buff[3] = '\0';
}
else
abbrev = 0;
for (tp = MonthDayTable; tp->name; tp++) {
if (abbrev) {
if (strncmp (buff, tp->name, 3) == 0) {
parse_date_lval.Number = tp->value;
return tp->type;
}
}
else if (strcmp (buff, tp->name) == 0) {
parse_date_lval.Number = tp->value;
return tp->type;
}
}
for (tp = TimezoneTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0) {
parse_date_lval.Number = tp->value;
return tp->type;
}
if (strcmp (buff, "dst") == 0)
return tDST;
for (tp = UnitsTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0) {
parse_date_lval.Number = tp->value;
return tp->type;
}
/* Strip off any plural and try the units table again. */
i = strlen (buff) - 1;
if (buff[i] == 's') {
buff[i] = '\0';
for (tp = UnitsTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0) {
parse_date_lval.Number = tp->value;
return tp->type;
}
buff[i] = 's'; /* Put back for "this" in OtherTable. */
}
for (tp = OtherTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0) {
parse_date_lval.Number = tp->value;
return tp->type;
}
/* Military timezones. */
if (buff[1] == '\0' && ISALPHA ((unsigned char) *buff)) {
for (tp = MilitaryTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0) {
parse_date_lval.Number = tp->value;
return tp->type;
}
}
/* Drop out any periods and try the timezone table again. */
for (i = 0, p = q = buff; *q; q++)
if (*q != '.')
*p++ = *q;
else
i++;
*p = '\0';
if (i)
for (tp = TimezoneTable; tp->name; tp++)
if (strcmp (buff, tp->name) == 0) {
parse_date_lval.Number = tp->value;
return tp->type;
}
return tID;
}
static int parse_date_lex () {
register unsigned char c;
register char *p;
char buff[20];
int Count;
int sign;
for (;;) {
while (ISSPACE ((unsigned char) *parse_date_Input))
parse_date_Input++;
if (ISDIGIT (c = *parse_date_Input) || c == '-' || c == '+') {
if (c == '-' || c == '+') {
sign = c == '-' ? -1 : 1;
if (!ISDIGIT (*++parse_date_Input))
/* skip the '-' sign */
continue;
}
else
sign = 0;
for (parse_date_lval.Number = 0; ISDIGIT (c = *parse_date_Input++);)
parse_date_lval.Number = 10 * parse_date_lval.Number + c - '0';
parse_date_Input--;
if (sign < 0)
parse_date_lval.Number = -parse_date_lval.Number;
return sign ? tSNUMBER : tUNUMBER;
}
if (ISALPHA (c)) {
for (p = buff; (c = *parse_date_Input++, ISALPHA (c)) || c == '.';)
if (p < &buff[sizeof buff - 1])
*p++ = c;
*p = '\0';
parse_date_Input--;
return LookupWord (buff);
}
if (c != '(')
return *parse_date_Input++;
Count = 0;
do {
c = *parse_date_Input++;
if (c == '\0')
return c;
if (c == '(')
Count++;
else if (c == ')')
Count--;
}
while (Count > 0);
}
}
/* Yield A - B, measured in seconds. */
static long difftm (struct tm *a, struct tm *b) {
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
long days = (
/* difference in day of year */
a->tm_yday - b->tm_yday
/* + intervening leap days */
+ ((ay >> 2) - (by >> 2))
- (ay / 100 - by / 100) + ((ay / 100 >> 2) - (by / 100 >> 2))
/* + difference in years * 365 */
+ (long) (ay - by) * 365);
return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
+ (a->tm_min - b->tm_min)) + (a->tm_sec - b->tm_sec));
}
time_t get_timestamp (const char *date) {
struct tm tm, tm0, *tmp;
time_t Start;
if (date == NULL) {
return time(NULL);
}
parse_date_Input = date;
Start = time(NULL);
tmp = localtime(&Start);
if (!tmp)
return -1;
parse_date_Year = tmp->tm_year + TM_YEAR_ORIGIN;
parse_date_Month = tmp->tm_mon + 1;
parse_date_Day = tmp->tm_mday;
parse_date_Hour = tmp->tm_hour;
parse_date_Minutes = tmp->tm_min;
parse_date_Seconds = tmp->tm_sec;
tm.tm_isdst = tmp->tm_isdst;
parse_date_Meridian = MER24;
parse_date_RelSeconds = 0;
parse_date_RelMinutes = 0;
parse_date_RelHour = 0;
parse_date_RelDay = 0;
parse_date_RelMonth = 0;
parse_date_RelYear = 0;
parse_date_HaveDate = 0;
parse_date_HaveDay = 0;
parse_date_HaveRel = 0;
parse_date_HaveTime = 0;
parse_date_HaveZone = 0;
if (parse_date ()
|| parse_date_HaveTime > 1 || parse_date_HaveZone > 1
|| parse_date_HaveDate > 1 || parse_date_HaveDay > 1)
return -1;
tm.tm_year = ToYear (parse_date_Year) - TM_YEAR_ORIGIN + parse_date_RelYear;
tm.tm_mon = parse_date_Month - 1 + parse_date_RelMonth;
tm.tm_mday = parse_date_Day + parse_date_RelDay;
if (parse_date_HaveTime
|| (parse_date_HaveRel && !parse_date_HaveDate
&& !parse_date_HaveDay)) {
tm.tm_hour = ToHour (parse_date_Hour, parse_date_Meridian);
if (tm.tm_hour < 0)
return -1;
tm.tm_min = parse_date_Minutes;
tm.tm_sec = parse_date_Seconds;
}
else {
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
}
tm.tm_hour += parse_date_RelHour;
tm.tm_min += parse_date_RelMinutes;
tm.tm_sec += parse_date_RelSeconds;
if (parse_date_HaveDate | parse_date_HaveDay | parse_date_HaveTime |
parse_date_RelDay | parse_date_RelMonth | parse_date_RelYear)
tm.tm_isdst = -1;
tm0 = tm;
Start = mktime (&tm);
if (Start == (time_t) - 1) {
/* Guard against falsely reporting errors near the time_t boundaries
when parsing times in other time zones. For example, if the min
time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead
of UTC, then the min localtime value is 1970-01-01 08:00:00; if
we apply mktime to 1970-01-01 00:00:00 we will get an error, so
we apply mktime to 1970-01-02 08:00:00 instead and adjust the time
zone by 24 hours to compensate. This algorithm assumes that
there is no DST transition within a day of the time_t boundaries. */
if (parse_date_HaveZone) {
tm = tm0;
if (tm.tm_year <= EPOCH - TM_YEAR_ORIGIN) {
tm.tm_mday++;
parse_date_Timezone -= 24 * 60;
}
else {
tm.tm_mday--;
parse_date_Timezone += 24 * 60;
}
Start = mktime (&tm);
}
if (Start == (time_t) - 1)
return Start;
}
if (parse_date_HaveDay && !parse_date_HaveDate) {
tm.tm_mday += ((parse_date_DayNumber - tm.tm_wday + 7) % 7
+ 7 * (parse_date_DayOrdinal -
(0 < parse_date_DayOrdinal)));
Start = mktime (&tm);
if (Start == (time_t) - 1)
return Start;
}
if (parse_date_HaveZone) {
long delta;
struct tm *gmt = gmtime (&Start);
if (!gmt)
return -1;
delta = parse_date_Timezone * 60L + difftm (&tm, gmt);
if ((Start + delta < Start) != (delta < 0))
return -1; /* time_t overflow */
Start += delta;
}
return Start;
}