#
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;
}
转载于:https://www.cnblogs.com/fx2008/archive/2011/09/27/2193011.html