GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/rcs/date.c Lines: 0 214 0.0 %
Date: 2017-11-13 Branches: 0 138 0.0 %

Line Branch Exec Source
1
#include <stdlib.h>
2
#include <string.h>
3
#define YYBYACC 1
4
#define YYMAJOR 1
5
#define YYMINOR 9
6
#define YYLEX yylex()
7
#define YYEMPTY -1
8
#define yyclearin (yychar=(YYEMPTY))
9
#define yyerrok (yyerrflag=0)
10
#define YYRECOVERING() (yyerrflag!=0)
11
#define YYPREFIX "yy"
12
#line 2 "date.y"
13
/*	$OpenBSD: date.y,v 1.14 2016/08/26 09:02:54 guenther Exp $	*/
14
15
/*
16
**  Originally written by Steven M. Bellovin <smb@research.att.com> while
17
**  at the University of North Carolina at Chapel Hill.  Later tweaked by
18
**  a couple of people on Usenet.  Completely overhauled by Rich $alz
19
**  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
20
**
21
**  This grammar has 10 shift/reduce conflicts.
22
**
23
**  This code is in the public domain and has no copyright.
24
*/
25
/* SUPPRESS 287 on yaccpar_sccsid *//* Unused static variable */
26
/* SUPPRESS 288 on yyerrlab *//* Label unused */
27
28
#include <ctype.h>
29
#include <err.h>
30
#include <string.h>
31
#include <time.h>
32
33
#include "rcsprog.h"
34
35
#define YEAR_EPOCH	1970
36
#define YEAR_TMORIGIN	1900
37
#define HOUR(x)		((time_t)(x) * 60)
38
#define SECSPERDAY	(24L * 60L * 60L)
39
40
41
/* An entry in the lexical lookup table */
42
typedef struct _TABLE {
43
	char	*name;
44
	int	type;
45
	time_t	value;
46
} TABLE;
47
48
49
/*  Daylight-savings mode:  on, off, or not yet known. */
50
typedef enum _DSTMODE {
51
	DSTon, DSToff, DSTmaybe
52
} DSTMODE;
53
54
/*  Meridian:  am, pm, or 24-hour style. */
55
typedef enum _MERIDIAN {
56
	MERam, MERpm, MER24
57
} MERIDIAN;
58
59
60
/*
61
 *  Global variables.  We could get rid of most of these by using a good
62
 *  union as the yacc stack.  (This routine was originally written before
63
 *  yacc had the %union construct.)  Maybe someday; right now we only use
64
 *  the %union very rarely.
65
 */
66
static const char	*yyInput;
67
static DSTMODE	yyDSTmode;
68
static time_t	yyDayOrdinal;
69
static time_t	yyDayNumber;
70
static int	yyHaveDate;
71
static int	yyHaveDay;
72
static int	yyHaveRel;
73
static int	yyHaveTime;
74
static int	yyHaveZone;
75
static time_t	yyTimezone;
76
static time_t	yyDay;
77
static time_t	yyHour;
78
static time_t	yyMinutes;
79
static time_t	yyMonth;
80
static time_t	yySeconds;
81
static time_t	yyYear;
82
static MERIDIAN	yyMeridian;
83
static time_t	yyRelMonth;
84
static time_t	yyRelSeconds;
85
86
87
static int	yyerror(const char *);
88
static int	yylex(void);
89
static int	yyparse(void);
90
static int	lookup(char *);
91
92
#line 83 "date.y"
93
#ifndef YYSTYPE_DEFINED
94
#define YYSTYPE_DEFINED
95
typedef union {
96
	time_t		Number;
97
	enum _MERIDIAN	Meridian;
98
} YYSTYPE;
99
#endif /* YYSTYPE_DEFINED */
100
#line 101 "date.c"
101
#define tAGO 257
102
#define tDAY 258
103
#define tDAYZONE 259
104
#define tID 260
105
#define tMERIDIAN 261
106
#define tMINUTE_UNIT 262
107
#define tMONTH 263
108
#define tMONTH_UNIT 264
109
#define tSEC_UNIT 265
110
#define tSNUMBER 266
111
#define tUNUMBER 267
112
#define tZONE 268
113
#define tDST 269
114
#define YYERRCODE 256
115
const short yylhs[] =
116
	{                                        -1,
117
    0,    0,    2,    2,    2,    2,    2,    2,    3,    3,
118
    3,    3,    3,    4,    4,    4,    6,    6,    6,    5,
119
    5,    5,    5,    5,    5,    5,    5,    7,    7,    9,
120
    9,    9,    9,    9,    9,    9,    9,    9,    8,    1,
121
    1,
122
};
123
const short yylen[] =
124
	{                                         2,
125
    0,    2,    1,    1,    1,    1,    1,    1,    2,    4,
126
    4,    6,    6,    1,    1,    2,    1,    2,    2,    3,
127
    5,    3,    3,    2,    4,    2,    3,    2,    1,    2,
128
    2,    1,    2,    2,    1,    2,    2,    1,    1,    0,
129
    1,
130
};
131
const short yydefred[] =
132
	{                                      1,
133
    0,    0,   15,   32,    0,   38,   35,    0,    0,    0,
134
    2,    3,    4,    5,    6,    7,    8,    0,   18,    0,
135
   31,   36,   33,   19,    9,   30,    0,   37,   34,    0,
136
    0,    0,   16,   28,    0,   23,   27,   22,    0,    0,
137
   25,   41,   11,    0,   10,    0,    0,   21,   13,   12,
138
};
139
const short yydgoto[] =
140
	{                                       1,
141
   45,   11,   12,   13,   14,   15,   16,   17,   18,
142
};
143
const short yysindex[] =
144
	{                                      0,
145
 -249,  -38,    0,    0, -260,    0,    0, -240,  -47, -248,
146
    0,    0,    0,    0,    0,    0,    0, -237,    0,  -18,
147
    0,    0,    0,    0,    0,    0, -262,    0,    0, -239,
148
 -238, -236,    0,    0, -235,    0,    0,    0,  -56,  -19,
149
    0,    0,    0, -234,    0, -232, -258,    0,    0,    0,};
150
const short yyrindex[] =
151
	{                                      0,
152
    0,    1,    0,    0,    0,    0,    0,    0,   69,   12,
153
    0,    0,    0,    0,    0,    0,    0,   23,    0,   34,
154
    0,    0,    0,    0,    0,    0,   67,    0,    0,    0,
155
    0,    0,    0,    0,    0,    0,    0,    0,   56,   45,
156
    0,    0,    0,    0,    0,    0,   56,    0,    0,    0,};
157
const short yygindex[] =
158
	{                                      0,
159
  -17,    0,    0,    0,    0,    0,    0,    0,    0,
160
};
161
#define YYTABLESIZE 337
162
const short yytable[] =
163
	{                                      32,
164
   17,   44,   42,   36,   37,   19,   20,   49,    2,    3,
165
   31,   14,    4,    5,    6,    7,    8,    9,   10,   34,
166
   33,   21,   29,   22,   23,   35,   38,   46,   39,   50,
167
   40,   41,   47,   24,   48,    0,    0,    0,    0,    0,
168
    0,    0,    0,    0,   20,    0,    0,    0,    0,    0,
169
    0,    0,    0,    0,    0,   40,    0,    0,    0,    0,
170
    0,    0,    0,    0,    0,    0,   26,    0,   39,    0,
171
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
172
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
173
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
174
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
175
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
176
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
177
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
178
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
179
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
180
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
181
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
182
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
183
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
184
    0,    0,    0,    0,   42,    0,    0,    0,    0,   43,
185
   24,    0,    0,   25,   26,   27,   28,   29,   30,    0,
186
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
187
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
188
    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
189
    0,    0,    0,    0,    0,    0,    0,    0,   17,   17,
190
    0,    0,   17,   17,   17,   17,   17,   17,   17,   14,
191
   14,    0,    0,   14,   14,   14,   14,   14,   14,   14,
192
   29,   29,    0,    0,   29,   29,   29,   29,   29,   29,
193
   29,   24,   24,    0,    0,   24,   24,   24,   24,   24,
194
   24,   24,   20,   20,    0,    0,   20,   20,   20,   20,
195
   20,   20,   20,   40,   40,    0,    0,   40,   40,   40,
196
   40,    0,   40,   40,   26,   26,    0,   39,   26,   26,
197
   26,   26,    0,    0,   26,   39,   39,
198
};
199
const short yycheck[] =
200
	{                                      47,
201
    0,   58,  261,  266,  267,   44,  267,  266,  258,  259,
202
   58,    0,  262,  263,  264,  265,  266,  267,  268,  257,
203
  269,  262,    0,  264,  265,   44,  266,   47,  267,   47,
204
  267,  267,  267,    0,  267,   -1,   -1,   -1,   -1,   -1,
205
   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,   -1,   -1,
206
   -1,   -1,   -1,   -1,   -1,    0,   -1,   -1,   -1,   -1,
207
   -1,   -1,   -1,   -1,   -1,   -1,    0,   -1,    0,   -1,
208
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
209
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
210
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
211
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
212
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
213
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
214
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
215
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
216
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
217
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
218
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
219
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
220
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
221
   -1,   -1,   -1,   -1,  261,   -1,   -1,   -1,   -1,  266,
222
  258,   -1,   -1,  261,  262,  263,  264,  265,  266,   -1,
223
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
224
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
225
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
226
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,  258,  259,
227
   -1,   -1,  262,  263,  264,  265,  266,  267,  268,  258,
228
  259,   -1,   -1,  262,  263,  264,  265,  266,  267,  268,
229
  258,  259,   -1,   -1,  262,  263,  264,  265,  266,  267,
230
  268,  258,  259,   -1,   -1,  262,  263,  264,  265,  266,
231
  267,  268,  258,  259,   -1,   -1,  262,  263,  264,  265,
232
  266,  267,  268,  258,  259,   -1,   -1,  262,  263,  264,
233
  265,   -1,  267,  268,  258,  259,   -1,  259,  262,  263,
234
  264,  265,   -1,   -1,  268,  267,  268,
235
};
236
#define YYFINAL 1
237
#ifndef YYDEBUG
238
#define YYDEBUG 0
239
#endif
240
#define YYMAXTOKEN 269
241
#if YYDEBUG
242
const char * const yyname[] =
243
	{
244
"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
245
0,0,0,0,0,0,0,0,0,0,"','",0,0,"'/'",0,0,0,0,0,0,0,0,0,0,"':'",0,0,0,0,0,0,0,0,0,
246
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
247
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
248
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
249
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
250
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"tAGO","tDAY",
251
"tDAYZONE","tID","tMERIDIAN","tMINUTE_UNIT","tMONTH","tMONTH_UNIT","tSEC_UNIT",
252
"tSNUMBER","tUNUMBER","tZONE","tDST",
253
};
254
const char * const yyrule[] =
255
	{"$accept : spec",
256
"spec :",
257
"spec : spec item",
258
"item : time",
259
"item : zone",
260
"item : date",
261
"item : day",
262
"item : rel",
263
"item : number",
264
"time : tUNUMBER tMERIDIAN",
265
"time : tUNUMBER ':' tUNUMBER o_merid",
266
"time : tUNUMBER ':' tUNUMBER tSNUMBER",
267
"time : tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid",
268
"time : tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER",
269
"zone : tZONE",
270
"zone : tDAYZONE",
271
"zone : tZONE tDST",
272
"day : tDAY",
273
"day : tDAY ','",
274
"day : tUNUMBER tDAY",
275
"date : tUNUMBER '/' tUNUMBER",
276
"date : tUNUMBER '/' tUNUMBER '/' tUNUMBER",
277
"date : tUNUMBER tSNUMBER tSNUMBER",
278
"date : tUNUMBER tMONTH tSNUMBER",
279
"date : tMONTH tUNUMBER",
280
"date : tMONTH tUNUMBER ',' tUNUMBER",
281
"date : tUNUMBER tMONTH",
282
"date : tUNUMBER tMONTH tUNUMBER",
283
"rel : relunit tAGO",
284
"rel : relunit",
285
"relunit : tUNUMBER tMINUTE_UNIT",
286
"relunit : tSNUMBER tMINUTE_UNIT",
287
"relunit : tMINUTE_UNIT",
288
"relunit : tSNUMBER tSEC_UNIT",
289
"relunit : tUNUMBER tSEC_UNIT",
290
"relunit : tSEC_UNIT",
291
"relunit : tSNUMBER tMONTH_UNIT",
292
"relunit : tUNUMBER tMONTH_UNIT",
293
"relunit : tMONTH_UNIT",
294
"number : tUNUMBER",
295
"o_merid :",
296
"o_merid : tMERIDIAN",
297
};
298
#endif
299
#ifdef YYSTACKSIZE
300
#undef YYMAXDEPTH
301
#define YYMAXDEPTH YYSTACKSIZE
302
#else
303
#ifdef YYMAXDEPTH
304
#define YYSTACKSIZE YYMAXDEPTH
305
#else
306
#define YYSTACKSIZE 10000
307
#define YYMAXDEPTH 10000
308
#endif
309
#endif
310
#define YYINITSTACKSIZE 200
311
/* LINTUSED */
312
int yydebug;
313
int yynerrs;
314
int yyerrflag;
315
int yychar;
316
short *yyssp;
317
YYSTYPE *yyvsp;
318
YYSTYPE yyval;
319
YYSTYPE yylval;
320
short *yyss;
321
short *yysslim;
322
YYSTYPE *yyvs;
323
unsigned int yystacksize;
324
int yyparse(void);
325
#line 299 "date.y"
326
327
/* Month and day table. */
328
static TABLE const MonthDayTable[] = {
329
	{ "january",	tMONTH,	1 },
330
	{ "february",	tMONTH,	2 },
331
	{ "march",	tMONTH,	3 },
332
	{ "april",	tMONTH,	4 },
333
	{ "may",	tMONTH,	5 },
334
	{ "june",	tMONTH,	6 },
335
	{ "july",	tMONTH,	7 },
336
	{ "august",	tMONTH,	8 },
337
	{ "september",	tMONTH,	9 },
338
	{ "sept",	tMONTH,	9 },
339
	{ "october",	tMONTH,	10 },
340
	{ "november",	tMONTH,	11 },
341
	{ "december",	tMONTH,	12 },
342
	{ "sunday",	tDAY,	0 },
343
	{ "monday",	tDAY,	1 },
344
	{ "tuesday",	tDAY,	2 },
345
	{ "tues",	tDAY,	2 },
346
	{ "wednesday",	tDAY,	3 },
347
	{ "wednes",	tDAY,	3 },
348
	{ "thursday",	tDAY,	4 },
349
	{ "thur",	tDAY,	4 },
350
	{ "thurs",	tDAY,	4 },
351
	{ "friday",	tDAY,	5 },
352
	{ "saturday",	tDAY,	6 },
353
	{ NULL }
354
};
355
356
/* Time units table. */
357
static TABLE const UnitsTable[] = {
358
	{ "year",	tMONTH_UNIT,	12 },
359
	{ "month",	tMONTH_UNIT,	1 },
360
	{ "fortnight",	tMINUTE_UNIT,	14 * 24 * 60 },
361
	{ "week",	tMINUTE_UNIT,	7 * 24 * 60 },
362
	{ "day",	tMINUTE_UNIT,	1 * 24 * 60 },
363
	{ "hour",	tMINUTE_UNIT,	60 },
364
	{ "minute",	tMINUTE_UNIT,	1 },
365
	{ "min",	tMINUTE_UNIT,	1 },
366
	{ "second",	tSEC_UNIT,	1 },
367
	{ "sec",	tSEC_UNIT,	1 },
368
	{ NULL }
369
};
370
371
/* Assorted relative-time words. */
372
static TABLE const OtherTable[] = {
373
	{ "tomorrow",	tMINUTE_UNIT,	1 * 24 * 60 },
374
	{ "yesterday",	tMINUTE_UNIT,	-1 * 24 * 60 },
375
	{ "today",	tMINUTE_UNIT,	0 },
376
	{ "now",	tMINUTE_UNIT,	0 },
377
	{ "last",	tUNUMBER,	-1 },
378
	{ "this",	tMINUTE_UNIT,	0 },
379
	{ "next",	tUNUMBER,	2 },
380
	{ "first",	tUNUMBER,	1 },
381
/*  { "second",		tUNUMBER,	2 }, */
382
	{ "third",	tUNUMBER,	3 },
383
	{ "fourth",	tUNUMBER,	4 },
384
	{ "fifth",	tUNUMBER,	5 },
385
	{ "sixth",	tUNUMBER,	6 },
386
	{ "seventh",	tUNUMBER,	7 },
387
	{ "eighth",	tUNUMBER,	8 },
388
	{ "ninth",	tUNUMBER,	9 },
389
	{ "tenth",	tUNUMBER,	10 },
390
	{ "eleventh",	tUNUMBER,	11 },
391
	{ "twelfth",	tUNUMBER,	12 },
392
	{ "ago",	tAGO,	1 },
393
	{ NULL }
394
};
395
396
/* The timezone table. */
397
/* Some of these are commented out because a time_t can't store a float. */
398
static TABLE const TimezoneTable[] = {
399
	{ "gmt",	tZONE,     HOUR( 0) },	/* Greenwich Mean */
400
	{ "ut",		tZONE,     HOUR( 0) },	/* Universal (Coordinated) */
401
	{ "utc",	tZONE,     HOUR( 0) },
402
	{ "wet",	tZONE,     HOUR( 0) },	/* Western European */
403
	{ "bst",	tDAYZONE,  HOUR( 0) },	/* British Summer */
404
	{ "wat",	tZONE,     HOUR( 1) },	/* West Africa */
405
	{ "at",		tZONE,     HOUR( 2) },	/* Azores */
406
#if	0
407
	/* For completeness.  BST is also British Summer, and GST is
408
	 * also Guam Standard. */
409
	{ "bst",	tZONE,     HOUR( 3) },	/* Brazil Standard */
410
	{ "gst",	tZONE,     HOUR( 3) },	/* Greenland Standard */
411
#endif
412
#if 0
413
	{ "nft",	tZONE,     HOUR(3.5) },	/* Newfoundland */
414
	{ "nst",	tZONE,     HOUR(3.5) },	/* Newfoundland Standard */
415
	{ "ndt",	tDAYZONE,  HOUR(3.5) },	/* Newfoundland Daylight */
416
#endif
417
	{ "ast",	tZONE,     HOUR( 4) },	/* Atlantic Standard */
418
	{ "adt",	tDAYZONE,  HOUR( 4) },	/* Atlantic Daylight */
419
	{ "est",	tZONE,     HOUR( 5) },	/* Eastern Standard */
420
	{ "edt",	tDAYZONE,  HOUR( 5) },	/* Eastern Daylight */
421
	{ "cst",	tZONE,     HOUR( 6) },	/* Central Standard */
422
	{ "cdt",	tDAYZONE,  HOUR( 6) },	/* Central Daylight */
423
	{ "mst",	tZONE,     HOUR( 7) },	/* Mountain Standard */
424
	{ "mdt",	tDAYZONE,  HOUR( 7) },	/* Mountain Daylight */
425
	{ "pst",	tZONE,     HOUR( 8) },	/* Pacific Standard */
426
	{ "pdt",	tDAYZONE,  HOUR( 8) },	/* Pacific Daylight */
427
	{ "yst",	tZONE,     HOUR( 9) },	/* Yukon Standard */
428
	{ "ydt",	tDAYZONE,  HOUR( 9) },	/* Yukon Daylight */
429
	{ "hst",	tZONE,     HOUR(10) },	/* Hawaii Standard */
430
	{ "hdt",	tDAYZONE,  HOUR(10) },	/* Hawaii Daylight */
431
	{ "cat",	tZONE,     HOUR(10) },	/* Central Alaska */
432
	{ "ahst",	tZONE,     HOUR(10) },	/* Alaska-Hawaii Standard */
433
	{ "nt",		tZONE,     HOUR(11) },	/* Nome */
434
	{ "idlw",	tZONE,     HOUR(12) },	/* International Date Line West */
435
	{ "cet",	tZONE,     -HOUR(1) },	/* Central European */
436
	{ "met",	tZONE,     -HOUR(1) },	/* Middle European */
437
	{ "mewt",	tZONE,     -HOUR(1) },	/* Middle European Winter */
438
	{ "mest",	tDAYZONE,  -HOUR(1) },	/* Middle European Summer */
439
	{ "swt",	tZONE,     -HOUR(1) },	/* Swedish Winter */
440
	{ "sst",	tDAYZONE,  -HOUR(1) },	/* Swedish Summer */
441
	{ "fwt",	tZONE,     -HOUR(1) },	/* French Winter */
442
	{ "fst",	tDAYZONE,  -HOUR(1) },	/* French Summer */
443
	{ "eet",	tZONE,     -HOUR(2) },	/* Eastern Europe, USSR Zone 1 */
444
	{ "bt",		tZONE,     -HOUR(3) },	/* Baghdad, USSR Zone 2 */
445
#if 0
446
	{ "it",		tZONE,     -HOUR(3.5) },/* Iran */
447
#endif
448
	{ "zp4",	tZONE,     -HOUR(4) },	/* USSR Zone 3 */
449
	{ "zp5",	tZONE,     -HOUR(5) },	/* USSR Zone 4 */
450
#if 0
451
	{ "ist",	tZONE,     -HOUR(5.5) },/* Indian Standard */
452
#endif
453
	{ "zp6",	tZONE,     -HOUR(6) },	/* USSR Zone 5 */
454
#if	0
455
	/* For completeness.  NST is also Newfoundland Stanard, and SST is
456
	 * also Swedish Summer. */
457
	{ "nst",	tZONE,     -HOUR(6.5) },/* North Sumatra */
458
	{ "sst",	tZONE,     -HOUR(7) },	/* South Sumatra, USSR Zone 6 */
459
#endif	/* 0 */
460
	{ "wast",	tZONE,     -HOUR(7) },	/* West Australian Standard */
461
	{ "wadt",	tDAYZONE,  -HOUR(7) },	/* West Australian Daylight */
462
#if 0
463
	{ "jt",		tZONE,     -HOUR(7.5) },/* Java (3pm in Cronusland!) */
464
#endif
465
	{ "cct",	tZONE,     -HOUR(8) },	/* China Coast, USSR Zone 7 */
466
	{ "jst",	tZONE,     -HOUR(9) },	/* Japan Standard, USSR Zone 8 */
467
#if 0
468
	{ "cast",	tZONE,     -HOUR(9.5) },/* Central Australian Standard */
469
	{ "cadt",	tDAYZONE,  -HOUR(9.5) },/* Central Australian Daylight */
470
#endif
471
	{ "east",	tZONE,     -HOUR(10) },	/* Eastern Australian Standard */
472
	{ "eadt",	tDAYZONE,  -HOUR(10) },	/* Eastern Australian Daylight */
473
	{ "gst",	tZONE,     -HOUR(10) },	/* Guam Standard, USSR Zone 9 */
474
	{ "nzt",	tZONE,     -HOUR(12) },	/* New Zealand */
475
	{ "nzst",	tZONE,     -HOUR(12) },	/* New Zealand Standard */
476
	{ "nzdt",	tDAYZONE,  -HOUR(12) },	/* New Zealand Daylight */
477
	{ "idle",	tZONE,     -HOUR(12) },	/* International Date Line East */
478
	{  NULL  }
479
};
480
481
/* Military timezone table. */
482
static TABLE const MilitaryTable[] = {
483
	{ "a",	tZONE,	HOUR(  1) },
484
	{ "b",	tZONE,	HOUR(  2) },
485
	{ "c",	tZONE,	HOUR(  3) },
486
	{ "d",	tZONE,	HOUR(  4) },
487
	{ "e",	tZONE,	HOUR(  5) },
488
	{ "f",	tZONE,	HOUR(  6) },
489
	{ "g",	tZONE,	HOUR(  7) },
490
	{ "h",	tZONE,	HOUR(  8) },
491
	{ "i",	tZONE,	HOUR(  9) },
492
	{ "k",	tZONE,	HOUR( 10) },
493
	{ "l",	tZONE,	HOUR( 11) },
494
	{ "m",	tZONE,	HOUR( 12) },
495
	{ "n",	tZONE,	HOUR(- 1) },
496
	{ "o",	tZONE,	HOUR(- 2) },
497
	{ "p",	tZONE,	HOUR(- 3) },
498
	{ "q",	tZONE,	HOUR(- 4) },
499
	{ "r",	tZONE,	HOUR(- 5) },
500
	{ "s",	tZONE,	HOUR(- 6) },
501
	{ "t",	tZONE,	HOUR(- 7) },
502
	{ "u",	tZONE,	HOUR(- 8) },
503
	{ "v",	tZONE,	HOUR(- 9) },
504
	{ "w",	tZONE,	HOUR(-10) },
505
	{ "x",	tZONE,	HOUR(-11) },
506
	{ "y",	tZONE,	HOUR(-12) },
507
	{ "z",	tZONE,	HOUR(  0) },
508
	{ NULL }
509
};
510
511
512
static int
513
yyerror(const char *s)
514
{
515
	char *str;
516
517
	if (isspace(yyInput[0]) || !isprint(yyInput[0]))
518
		(void)xasprintf(&str,
519
		    "%s: unexpected char 0x%02x in date string", s, yyInput[0]);
520
	else
521
		(void)xasprintf(&str, "%s: unexpected %s in date string",
522
		    s, yyInput);
523
524
	warnx("%s", str);
525
	free(str);
526
	return (0);
527
}
528
529
530
static time_t
531
ToSeconds(time_t Hours, time_t Minutes, time_t	Seconds, MERIDIAN Meridian)
532
{
533
	if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
534
		return (-1);
535
536
	switch (Meridian) {
537
	case MER24:
538
		if (Hours < 0 || Hours > 23)
539
			return (-1);
540
		return (Hours * 60L + Minutes) * 60L + Seconds;
541
	case MERam:
542
		if (Hours < 1 || Hours > 12)
543
			return (-1);
544
		if (Hours == 12)
545
			Hours = 0;
546
		return (Hours * 60L + Minutes) * 60L + Seconds;
547
	case MERpm:
548
		if (Hours < 1 || Hours > 12)
549
			return (-1);
550
		if (Hours == 12)
551
			Hours = 0;
552
		return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
553
	default:
554
		return (-1);
555
	}
556
	/* NOTREACHED */
557
}
558
559
560
/* Year is either
561
 * A negative number, which means to use its absolute value (why?)
562
 * A number from 0 to 99, which means a year from 1900 to 1999, or
563
 * The actual year (>=100).
564
 */
565
static time_t
566
Convert(time_t Month, time_t Day, time_t Year, time_t Hours, time_t Minutes,
567
    time_t Seconds, MERIDIAN Meridian, DSTMODE DSTmode)
568
{
569
	static int DaysInMonth[12] = {
570
		31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
571
	};
572
	time_t	tod;
573
	time_t	julian;
574
	int	i;
575
576
	if (Year < 0)
577
		Year = -Year;
578
	if (Year < 69)
579
		Year += 2000;
580
	else if (Year < 100) {
581
		Year += 1900;
582
		if (Year < YEAR_EPOCH)
583
			Year += 100;
584
	}
585
	DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
586
	    ? 29 : 28;
587
	/* XXX Sloppily check for 2038 if time_t is 32 bits */
588
	if (Year < YEAR_EPOCH ||
589
	    (sizeof(time_t) == sizeof(int) && Year > 2038) ||
590
	    Month < 1 || Month > 12 ||
591
	    /* Lint fluff:  "conversion from long may lose accuracy" */
592
	     Day < 1 || Day > DaysInMonth[(int)--Month])
593
		return (-1);
594
595
	for (julian = Day - 1, i = 0; i < Month; i++)
596
		julian += DaysInMonth[i];
597
598
	for (i = YEAR_EPOCH; i < Year; i++)
599
		julian += 365 + (i % 4 == 0);
600
	julian *= SECSPERDAY;
601
	julian += yyTimezone * 60L;
602
603
	if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
604
		return (-1);
605
	julian += tod;
606
	if ((DSTmode == DSTon) ||
607
	    (DSTmode == DSTmaybe && localtime(&julian)->tm_isdst))
608
	julian -= 60 * 60;
609
	return (julian);
610
}
611
612
613
static time_t
614
DSTcorrect(time_t Start, time_t Future)
615
{
616
	time_t	StartDay;
617
	time_t	FutureDay;
618
619
	StartDay = (localtime(&Start)->tm_hour + 1) % 24;
620
	FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
621
	return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
622
}
623
624
625
static time_t
626
RelativeDate(time_t Start, time_t DayOrdinal, time_t DayNumber)
627
{
628
	struct tm	*tm;
629
	time_t	now;
630
631
	now = Start;
632
	tm = localtime(&now);
633
	now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
634
	now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
635
	return DSTcorrect(Start, now);
636
}
637
638
639
static time_t
640
RelativeMonth(time_t Start, time_t RelMonth)
641
{
642
	struct tm	*tm;
643
	time_t	Month;
644
	time_t	Year;
645
646
	if (RelMonth == 0)
647
		return (0);
648
	tm = localtime(&Start);
649
	Month = 12 * (tm->tm_year + 1900) + tm->tm_mon + RelMonth;
650
	Year = Month / 12;
651
	Month = Month % 12 + 1;
652
	return DSTcorrect(Start,
653
	    Convert(Month, (time_t)tm->tm_mday, Year,
654
	    (time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
655
	    MER24, DSTmaybe));
656
}
657
658
659
static int
660
lookup(char *buff)
661
{
662
	size_t		len;
663
	char		*p, *q;
664
	int		i, abbrev;
665
	const TABLE	*tp;
666
667
	/* Make it lowercase. */
668
	for (p = buff; *p; p++)
669
		if (isupper(*p))
670
			*p = tolower(*p);
671
672
	if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
673
		yylval.Meridian = MERam;
674
		return (tMERIDIAN);
675
	}
676
	if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
677
		yylval.Meridian = MERpm;
678
		return (tMERIDIAN);
679
	}
680
681
	len = strlen(buff);
682
	/* See if we have an abbreviation for a month. */
683
	if (len == 3)
684
		abbrev = 1;
685
	else if (len == 4 && buff[3] == '.') {
686
		abbrev = 1;
687
		buff[3] = '\0';
688
		--len;
689
	} else
690
		abbrev = 0;
691
692
	for (tp = MonthDayTable; tp->name; tp++) {
693
		if (abbrev) {
694
			if (strncmp(buff, tp->name, 3) == 0) {
695
				yylval.Number = tp->value;
696
				return (tp->type);
697
			}
698
		} else if (strcmp(buff, tp->name) == 0) {
699
			yylval.Number = tp->value;
700
			return (tp->type);
701
		}
702
	}
703
704
	for (tp = TimezoneTable; tp->name; tp++)
705
		if (strcmp(buff, tp->name) == 0) {
706
			yylval.Number = tp->value;
707
			return (tp->type);
708
		}
709
710
	if (strcmp(buff, "dst") == 0)
711
		return (tDST);
712
713
	for (tp = UnitsTable; tp->name; tp++)
714
		if (strcmp(buff, tp->name) == 0) {
715
			yylval.Number = tp->value;
716
			return (tp->type);
717
		}
718
719
	/* Strip off any plural and try the units table again. */
720
	if (len != 0 && buff[len - 1] == 's') {
721
		buff[len - 1] = '\0';
722
		for (tp = UnitsTable; tp->name; tp++)
723
			if (strcmp(buff, tp->name) == 0) {
724
				yylval.Number = tp->value;
725
				return (tp->type);
726
			}
727
		buff[len - 1] = 's';	/* Put back for "this" in OtherTable. */
728
	}
729
730
	for (tp = OtherTable; tp->name; tp++)
731
		if (strcmp(buff, tp->name) == 0) {
732
			yylval.Number = tp->value;
733
			return (tp->type);
734
		}
735
736
	/* Military timezones. */
737
	if (len == 1 && isalpha(*buff)) {
738
		for (tp = MilitaryTable; tp->name; tp++)
739
			if (strcmp(buff, tp->name) == 0) {
740
				yylval.Number = tp->value;
741
				return (tp->type);
742
			}
743
	}
744
745
	/* Drop out any periods and try the timezone table again. */
746
	for (i = 0, p = q = buff; *q; q++)
747
		if (*q != '.')
748
			*p++ = *q;
749
		else
750
			i++;
751
	*p = '\0';
752
	if (i)
753
		for (tp = TimezoneTable; tp->name; tp++)
754
			if (strcmp(buff, tp->name) == 0) {
755
				yylval.Number = tp->value;
756
				return (tp->type);
757
			}
758
759
	return (tID);
760
}
761
762
763
static int
764
yylex(void)
765
{
766
	char	c, *p, buff[20];
767
	int	count, sign;
768
769
	for (;;) {
770
		while (isspace(*yyInput))
771
			yyInput++;
772
773
		if (isdigit(c = *yyInput) || c == '-' || c == '+') {
774
			if (c == '-' || c == '+') {
775
				sign = c == '-' ? -1 : 1;
776
				if (!isdigit(*++yyInput))
777
					/* skip the '-' sign */
778
					continue;
779
			}
780
			else
781
				sign = 0;
782
783
			for (yylval.Number = 0; isdigit(c = *yyInput++); )
784
				yylval.Number = 10 * yylval.Number + c - '0';
785
			yyInput--;
786
			if (sign < 0)
787
				yylval.Number = -yylval.Number;
788
			return sign ? tSNUMBER : tUNUMBER;
789
		}
790
791
		if (isalpha(c)) {
792
			for (p = buff; isalpha(c = *yyInput++) || c == '.'; )
793
				if (p < &buff[sizeof buff - 1])
794
					*p++ = c;
795
			*p = '\0';
796
			yyInput--;
797
			return lookup(buff);
798
		}
799
		if (c != '(')
800
			return *yyInput++;
801
802
		count = 0;
803
		do {
804
			c = *yyInput++;
805
			if (c == '\0')
806
				return (c);
807
			if (c == '(')
808
				count++;
809
			else if (c == ')')
810
				count--;
811
		} while (count > 0);
812
	}
813
}
814
815
/* Yield A - B, measured in seconds.  */
816
static long
817
difftm(struct tm *a, struct tm *b)
818
{
819
	int ay = a->tm_year + (YEAR_TMORIGIN - 1);
820
	int by = b->tm_year + (YEAR_TMORIGIN - 1);
821
	int days = (
822
	    /* difference in day of year */
823
	    a->tm_yday - b->tm_yday
824
	    /* + intervening leap days */
825
	    +  ((ay >> 2) - (by >> 2))
826
	    -  (ay/100 - by/100)
827
	    +  ((ay/100 >> 2) - (by/100 >> 2))
828
	    /* + difference in years * 365 */
829
	    +  (long)(ay-by) * 365);
830
	return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour))
831
	    + (a->tm_min - b->tm_min)) + (a->tm_sec - b->tm_sec));
832
}
833
834
/*
835
 * date_parse()
836
 *
837
 * Returns the number of seconds since the Epoch corresponding to the date.
838
 */
839
time_t
840
date_parse(const char *p)
841
{
842
	struct tm	gmt, tm;
843
	time_t		Start, tod, nowtime, tz;
844
845
	yyInput = p;
846
847
	if (time(&nowtime) == -1 || !gmtime_r(&nowtime, &gmt) ||
848
	    !localtime_r(&nowtime, &tm))
849
		return -1;
850
851
	tz = difftm(&gmt, &tm) / 60;
852
853
	if (tm.tm_isdst)
854
		tz += 60;
855
856
	yyYear = tm.tm_year + 1900;
857
	yyMonth = tm.tm_mon + 1;
858
	yyDay = tm.tm_mday;
859
	yyTimezone = tz;
860
	yyDSTmode = DSTmaybe;
861
	yyHour = 0;
862
	yyMinutes = 0;
863
	yySeconds = 0;
864
	yyMeridian = MER24;
865
	yyRelSeconds = 0;
866
	yyRelMonth = 0;
867
	yyHaveDate = 0;
868
	yyHaveDay = 0;
869
	yyHaveRel = 0;
870
	yyHaveTime = 0;
871
	yyHaveZone = 0;
872
873
	if (yyparse() || yyHaveTime > 1 || yyHaveZone > 1 ||
874
	    yyHaveDate > 1 || yyHaveDay > 1)
875
		return (-1);
876
877
	if (yyHaveDate || yyHaveTime || yyHaveDay) {
878
		Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes,
879
		    yySeconds, yyMeridian, yyDSTmode);
880
		if (Start < 0)
881
			return (-1);
882
	} else {
883
		Start = nowtime;
884
		if (!yyHaveRel)
885
			Start -= ((tm.tm_hour * 60L + tm.tm_min) * 60L) +
886
			    tm.tm_sec;
887
	}
888
889
	Start += yyRelSeconds;
890
	Start += RelativeMonth(Start, yyRelMonth);
891
892
	if (yyHaveDay && !yyHaveDate) {
893
		tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
894
		Start += tod;
895
	}
896
897
	return Start;
898
}
899
900
#if defined(TEST)
901
/* ARGSUSED */
902
int
903
main(int argc, char **argv)
904
{
905
	char	buff[128];
906
	time_t	d;
907
908
	(void)printf("Enter date, or blank line to exit.\n\t> ");
909
	(void)fflush(stdout);
910
	while (fgets(buff, sizeof(buff), stdin) && buff[0]) {
911
		d = date_parse(buff);
912
		if (d == -1)
913
			(void)printf("Bad format - couldn't convert.\n");
914
		else
915
			(void)printf("%s", ctime(&d));
916
		(void)printf("\t> ");
917
		(void)fflush(stdout);
918
	}
919
920
	return (0);
921
}
922
#endif	/* defined(TEST) */
923
#line 916 "date.c"
924
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
925
static int yygrowstack(void)
926
{
927
    unsigned int newsize;
928
    long sslen;
929
    short *newss;
930
    YYSTYPE *newvs;
931
932
    if ((newsize = yystacksize) == 0)
933
        newsize = YYINITSTACKSIZE;
934
    else if (newsize >= YYMAXDEPTH)
935
        return -1;
936
    else if ((newsize *= 2) > YYMAXDEPTH)
937
        newsize = YYMAXDEPTH;
938
    sslen = yyssp - yyss;
939
#ifdef SIZE_MAX
940
#define YY_SIZE_MAX SIZE_MAX
941
#else
942
#define YY_SIZE_MAX 0xffffffffU
943
#endif
944
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newss)
945
        goto bail;
946
    newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
947
      (short *)malloc(newsize * sizeof *newss); /* overflow check above */
948
    if (newss == NULL)
949
        goto bail;
950
    yyss = newss;
951
    yyssp = newss + sslen;
952
    if (newsize && YY_SIZE_MAX / newsize < sizeof *newvs)
953
        goto bail;
954
    newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
955
      (YYSTYPE *)malloc(newsize * sizeof *newvs); /* overflow check above */
956
    if (newvs == NULL)
957
        goto bail;
958
    yyvs = newvs;
959
    yyvsp = newvs + sslen;
960
    yystacksize = newsize;
961
    yysslim = yyss + newsize - 1;
962
    return 0;
963
bail:
964
    if (yyss)
965
            free(yyss);
966
    if (yyvs)
967
            free(yyvs);
968
    yyss = yyssp = NULL;
969
    yyvs = yyvsp = NULL;
970
    yystacksize = 0;
971
    return -1;
972
}
973
974
#define YYABORT goto yyabort
975
#define YYREJECT goto yyabort
976
#define YYACCEPT goto yyaccept
977
#define YYERROR goto yyerrlab
978
int
979
yyparse(void)
980
{
981
    int yym, yyn, yystate;
982
#if YYDEBUG
983
    const char *yys;
984
985
    if ((yys = getenv("YYDEBUG")))
986
    {
987
        yyn = *yys;
988
        if (yyn >= '0' && yyn <= '9')
989
            yydebug = yyn - '0';
990
    }
991
#endif /* YYDEBUG */
992
993
    yynerrs = 0;
994
    yyerrflag = 0;
995
    yychar = (-1);
996
997
    if (yyss == NULL && yygrowstack()) goto yyoverflow;
998
    yyssp = yyss;
999
    yyvsp = yyvs;
1000
    *yyssp = yystate = 0;
1001
1002
yyloop:
1003
    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1004
    if (yychar < 0)
1005
    {
1006
        if ((yychar = yylex()) < 0) yychar = 0;
1007
#if YYDEBUG
1008
        if (yydebug)
1009
        {
1010
            yys = 0;
1011
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1012
            if (!yys) yys = "illegal-symbol";
1013
            printf("%sdebug: state %d, reading %d (%s)\n",
1014
                    YYPREFIX, yystate, yychar, yys);
1015
        }
1016
#endif
1017
    }
1018
    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1019
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1020
    {
1021
#if YYDEBUG
1022
        if (yydebug)
1023
            printf("%sdebug: state %d, shifting to state %d\n",
1024
                    YYPREFIX, yystate, yytable[yyn]);
1025
#endif
1026
        if (yyssp >= yysslim && yygrowstack())
1027
        {
1028
            goto yyoverflow;
1029
        }
1030
        *++yyssp = yystate = yytable[yyn];
1031
        *++yyvsp = yylval;
1032
        yychar = (-1);
1033
        if (yyerrflag > 0)  --yyerrflag;
1034
        goto yyloop;
1035
    }
1036
    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1037
            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1038
    {
1039
        yyn = yytable[yyn];
1040
        goto yyreduce;
1041
    }
1042
    if (yyerrflag) goto yyinrecovery;
1043
#if defined(__GNUC__)
1044
    goto yynewerror;
1045
#endif
1046
yynewerror:
1047
    yyerror("syntax error");
1048
#if defined(__GNUC__)
1049
    goto yyerrlab;
1050
#endif
1051
yyerrlab:
1052
    ++yynerrs;
1053
yyinrecovery:
1054
    if (yyerrflag < 3)
1055
    {
1056
        yyerrflag = 3;
1057
        for (;;)
1058
        {
1059
            if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
1060
                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1061
            {
1062
#if YYDEBUG
1063
                if (yydebug)
1064
                    printf("%sdebug: state %d, error recovery shifting\
1065
 to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
1066
#endif
1067
                if (yyssp >= yysslim && yygrowstack())
1068
                {
1069
                    goto yyoverflow;
1070
                }
1071
                *++yyssp = yystate = yytable[yyn];
1072
                *++yyvsp = yylval;
1073
                goto yyloop;
1074
            }
1075
            else
1076
            {
1077
#if YYDEBUG
1078
                if (yydebug)
1079
                    printf("%sdebug: error recovery discarding state %d\n",
1080
                            YYPREFIX, *yyssp);
1081
#endif
1082
                if (yyssp <= yyss) goto yyabort;
1083
                --yyssp;
1084
                --yyvsp;
1085
            }
1086
        }
1087
    }
1088
    else
1089
    {
1090
        if (yychar == 0) goto yyabort;
1091
#if YYDEBUG
1092
        if (yydebug)
1093
        {
1094
            yys = 0;
1095
            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1096
            if (!yys) yys = "illegal-symbol";
1097
            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1098
                    YYPREFIX, yystate, yychar, yys);
1099
        }
1100
#endif
1101
        yychar = (-1);
1102
        goto yyloop;
1103
    }
1104
yyreduce:
1105
#if YYDEBUG
1106
    if (yydebug)
1107
        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1108
                YYPREFIX, yystate, yyn, yyrule[yyn]);
1109
#endif
1110
    yym = yylen[yyn];
1111
    if (yym)
1112
        yyval = yyvsp[1-yym];
1113
    else
1114
        memset(&yyval, 0, sizeof yyval);
1115
    switch (yyn)
1116
    {
1117
case 3:
1118
#line 101 "date.y"
1119
{
1120
		yyHaveTime++;
1121
	}
1122
break;
1123
case 4:
1124
#line 104 "date.y"
1125
{
1126
		yyHaveZone++;
1127
	}
1128
break;
1129
case 5:
1130
#line 107 "date.y"
1131
{
1132
		yyHaveDate++;
1133
	}
1134
break;
1135
case 6:
1136
#line 110 "date.y"
1137
{
1138
		yyHaveDay++;
1139
	}
1140
break;
1141
case 7:
1142
#line 113 "date.y"
1143
{
1144
		yyHaveRel++;
1145
	}
1146
break;
1147
case 9:
1148
#line 119 "date.y"
1149
{
1150
		yyHour = yyvsp[-1].Number;
1151
		yyMinutes = 0;
1152
		yySeconds = 0;
1153
		yyMeridian = yyvsp[0].Meridian;
1154
	}
1155
break;
1156
case 10:
1157
#line 125 "date.y"
1158
{
1159
		yyHour = yyvsp[-3].Number;
1160
		yyMinutes = yyvsp[-1].Number;
1161
		yySeconds = 0;
1162
		yyMeridian = yyvsp[0].Meridian;
1163
	}
1164
break;
1165
case 11:
1166
#line 131 "date.y"
1167
{
1168
		yyHour = yyvsp[-3].Number;
1169
		yyMinutes = yyvsp[-1].Number;
1170
		yyMeridian = MER24;
1171
		yyDSTmode = DSToff;
1172
		yyTimezone = - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60);
1173
	}
1174
break;
1175
case 12:
1176
#line 138 "date.y"
1177
{
1178
		yyHour = yyvsp[-5].Number;
1179
		yyMinutes = yyvsp[-3].Number;
1180
		yySeconds = yyvsp[-1].Number;
1181
		yyMeridian = yyvsp[0].Meridian;
1182
	}
1183
break;
1184
case 13:
1185
#line 144 "date.y"
1186
{
1187
		yyHour = yyvsp[-5].Number;
1188
		yyMinutes = yyvsp[-3].Number;
1189
		yySeconds = yyvsp[-1].Number;
1190
		yyMeridian = MER24;
1191
		yyDSTmode = DSToff;
1192
		yyTimezone = - (yyvsp[0].Number % 100 + (yyvsp[0].Number / 100) * 60);
1193
	}
1194
break;
1195
case 14:
1196
#line 154 "date.y"
1197
{
1198
		yyTimezone = yyvsp[0].Number;
1199
		yyDSTmode = DSToff;
1200
	}
1201
break;
1202
case 15:
1203
#line 158 "date.y"
1204
{
1205
		yyTimezone = yyvsp[0].Number;
1206
		yyDSTmode = DSTon;
1207
	}
1208
break;
1209
case 16:
1210
#line 162 "date.y"
1211
{
1212
		yyTimezone = yyvsp[-1].Number;
1213
		yyDSTmode = DSTon;
1214
	}
1215
break;
1216
case 17:
1217
#line 168 "date.y"
1218
{
1219
		yyDayOrdinal = 1;
1220
		yyDayNumber = yyvsp[0].Number;
1221
	}
1222
break;
1223
case 18:
1224
#line 172 "date.y"
1225
{
1226
		yyDayOrdinal = 1;
1227
		yyDayNumber = yyvsp[-1].Number;
1228
	}
1229
break;
1230
case 19:
1231
#line 176 "date.y"
1232
{
1233
		yyDayOrdinal = yyvsp[-1].Number;
1234
		yyDayNumber = yyvsp[0].Number;
1235
	}
1236
break;
1237
case 20:
1238
#line 182 "date.y"
1239
{
1240
		yyMonth = yyvsp[-2].Number;
1241
		yyDay = yyvsp[0].Number;
1242
	}
1243
break;
1244
case 21:
1245
#line 186 "date.y"
1246
{
1247
		if (yyvsp[-4].Number >= 100) {
1248
			yyYear = yyvsp[-4].Number;
1249
			yyMonth = yyvsp[-2].Number;
1250
			yyDay = yyvsp[0].Number;
1251
		} else {
1252
			yyMonth = yyvsp[-4].Number;
1253
			yyDay = yyvsp[-2].Number;
1254
			yyYear = yyvsp[0].Number;
1255
		}
1256
	}
1257
break;
1258
case 22:
1259
#line 197 "date.y"
1260
{
1261
		/* ISO 8601 format.  yyyy-mm-dd.  */
1262
		yyYear = yyvsp[-2].Number;
1263
		yyMonth = -yyvsp[-1].Number;
1264
		yyDay = -yyvsp[0].Number;
1265
	}
1266
break;
1267
case 23:
1268
#line 203 "date.y"
1269
{
1270
		/* e.g. 17-JUN-1992.  */
1271
		yyDay = yyvsp[-2].Number;
1272
		yyMonth = yyvsp[-1].Number;
1273
		yyYear = -yyvsp[0].Number;
1274
	}
1275
break;
1276
case 24:
1277
#line 209 "date.y"
1278
{
1279
		yyMonth = yyvsp[-1].Number;
1280
		yyDay = yyvsp[0].Number;
1281
	}
1282
break;
1283
case 25:
1284
#line 213 "date.y"
1285
{
1286
		yyMonth = yyvsp[-3].Number;
1287
		yyDay = yyvsp[-2].Number;
1288
		yyYear = yyvsp[0].Number;
1289
	}
1290
break;
1291
case 26:
1292
#line 218 "date.y"
1293
{
1294
		yyMonth = yyvsp[0].Number;
1295
		yyDay = yyvsp[-1].Number;
1296
	}
1297
break;
1298
case 27:
1299
#line 222 "date.y"
1300
{
1301
		yyMonth = yyvsp[-1].Number;
1302
		yyDay = yyvsp[-2].Number;
1303
		yyYear = yyvsp[0].Number;
1304
	}
1305
break;
1306
case 28:
1307
#line 229 "date.y"
1308
{
1309
		yyRelSeconds = -yyRelSeconds;
1310
		yyRelMonth = -yyRelMonth;
1311
	}
1312
break;
1313
case 30:
1314
#line 236 "date.y"
1315
{
1316
		yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number * 60L;
1317
	}
1318
break;
1319
case 31:
1320
#line 239 "date.y"
1321
{
1322
		yyRelSeconds += yyvsp[-1].Number * yyvsp[0].Number * 60L;
1323
	}
1324
break;
1325
case 32:
1326
#line 242 "date.y"
1327
{
1328
		yyRelSeconds += yyvsp[0].Number * 60L;
1329
	}
1330
break;
1331
case 33:
1332
#line 245 "date.y"
1333
{
1334
		yyRelSeconds += yyvsp[-1].Number;
1335
	}
1336
break;
1337
case 34:
1338
#line 248 "date.y"
1339
{
1340
		yyRelSeconds += yyvsp[-1].Number;
1341
	}
1342
break;
1343
case 35:
1344
#line 251 "date.y"
1345
{
1346
		yyRelSeconds++;
1347
	}
1348
break;
1349
case 36:
1350
#line 254 "date.y"
1351
{
1352
		yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1353
	}
1354
break;
1355
case 37:
1356
#line 257 "date.y"
1357
{
1358
		yyRelMonth += yyvsp[-1].Number * yyvsp[0].Number;
1359
	}
1360
break;
1361
case 38:
1362
#line 260 "date.y"
1363
{
1364
		yyRelMonth += yyvsp[0].Number;
1365
	}
1366
break;
1367
case 39:
1368
#line 265 "date.y"
1369
{
1370
		if (yyHaveTime && yyHaveDate && !yyHaveRel)
1371
			yyYear = yyvsp[0].Number;
1372
		else {
1373
			if (yyvsp[0].Number > 10000) {
1374
				yyHaveDate++;
1375
				yyDay= (yyvsp[0].Number)%100;
1376
				yyMonth= (yyvsp[0].Number/100)%100;
1377
				yyYear = yyvsp[0].Number/10000;
1378
			} else {
1379
				yyHaveTime++;
1380
				if (yyvsp[0].Number < 100) {
1381
					yyHour = yyvsp[0].Number;
1382
					yyMinutes = 0;
1383
				} else {
1384
					yyHour = yyvsp[0].Number / 100;
1385
					yyMinutes = yyvsp[0].Number % 100;
1386
				}
1387
				yySeconds = 0;
1388
				yyMeridian = MER24;
1389
			}
1390
		}
1391
	}
1392
break;
1393
case 40:
1394
#line 290 "date.y"
1395
{
1396
		yyval.Meridian = MER24;
1397
	}
1398
break;
1399
case 41:
1400
#line 293 "date.y"
1401
{
1402
		yyval.Meridian = yyvsp[0].Meridian;
1403
	}
1404
break;
1405
#line 1398 "date.c"
1406
    }
1407
    yyssp -= yym;
1408
    yystate = *yyssp;
1409
    yyvsp -= yym;
1410
    yym = yylhs[yyn];
1411
    if (yystate == 0 && yym == 0)
1412
    {
1413
#if YYDEBUG
1414
        if (yydebug)
1415
            printf("%sdebug: after reduction, shifting from state 0 to\
1416
 state %d\n", YYPREFIX, YYFINAL);
1417
#endif
1418
        yystate = YYFINAL;
1419
        *++yyssp = YYFINAL;
1420
        *++yyvsp = yyval;
1421
        if (yychar < 0)
1422
        {
1423
            if ((yychar = yylex()) < 0) yychar = 0;
1424
#if YYDEBUG
1425
            if (yydebug)
1426
            {
1427
                yys = 0;
1428
                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1429
                if (!yys) yys = "illegal-symbol";
1430
                printf("%sdebug: state %d, reading %d (%s)\n",
1431
                        YYPREFIX, YYFINAL, yychar, yys);
1432
            }
1433
#endif
1434
        }
1435
        if (yychar == 0) goto yyaccept;
1436
        goto yyloop;
1437
    }
1438
    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1439
            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1440
        yystate = yytable[yyn];
1441
    else
1442
        yystate = yydgoto[yym];
1443
#if YYDEBUG
1444
    if (yydebug)
1445
        printf("%sdebug: after reduction, shifting from state %d \
1446
to state %d\n", YYPREFIX, *yyssp, yystate);
1447
#endif
1448
    if (yyssp >= yysslim && yygrowstack())
1449
    {
1450
        goto yyoverflow;
1451
    }
1452
    *++yyssp = yystate;
1453
    *++yyvsp = yyval;
1454
    goto yyloop;
1455
yyoverflow:
1456
    yyerror("yacc stack overflow");
1457
yyabort:
1458
    if (yyss)
1459
            free(yyss);
1460
    if (yyvs)
1461
            free(yyvs);
1462
    yyss = yyssp = NULL;
1463
    yyvs = yyvsp = NULL;
1464
    yystacksize = 0;
1465
    return (1);
1466
yyaccept:
1467
    if (yyss)
1468
            free(yyss);
1469
    if (yyvs)
1470
            free(yyvs);
1471
    yyss = yyssp = NULL;
1472
    yyvs = yyvsp = NULL;
1473
    yystacksize = 0;
1474
    return (0);
1475
}