xref: /onnv-gate/usr/src/cmd/backup/lib/getdate.y (revision 0:68f95e015346)
1*0Sstevel@tonic-gate %{
2*0Sstevel@tonic-gate /*
3*0Sstevel@tonic-gate  * Copyright (c) 1998 by Sun Microsystems, Inc.
4*0Sstevel@tonic-gate  * All rights reserved.
5*0Sstevel@tonic-gate  */
6*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*0Sstevel@tonic-gate 
8*0Sstevel@tonic-gate /* $OrigRevision: 2.1 $
9*0Sstevel@tonic-gate **
10*0Sstevel@tonic-gate **  Originally written by Steven M. Bellovin <smb@research.att.com> while
11*0Sstevel@tonic-gate **  at the University of North Carolina at Chapel Hill.  Later tweaked by
12*0Sstevel@tonic-gate **  a couple of people on Usenet.  Completely overhauled by Rich $alz
13*0Sstevel@tonic-gate **  <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990;
14*0Sstevel@tonic-gate **  send any email to Rich.
15*0Sstevel@tonic-gate **
16*0Sstevel@tonic-gate **  This grammar has eight shift/reduce conflicts.
17*0Sstevel@tonic-gate **
18*0Sstevel@tonic-gate **  This code is in the public domain and has no copyright.
19*0Sstevel@tonic-gate */
20*0Sstevel@tonic-gate /* SUPPRESS 287 on yaccpar_sccsid *//* Unusd static variable */
21*0Sstevel@tonic-gate /* SUPPRESS 288 on yyerrlab *//* Label unused */
22*0Sstevel@tonic-gate #include <stdio.h>
23*0Sstevel@tonic-gate #include <ctype.h>
24*0Sstevel@tonic-gate 
25*0Sstevel@tonic-gate #include <sys/types.h>
26*0Sstevel@tonic-gate #define NEED_TZSET
27*0Sstevel@tonic-gate struct timeb {
28*0Sstevel@tonic-gate     time_t		time;		/* Seconds since the epoch	*/
29*0Sstevel@tonic-gate     unsigned short	millitm;	/* Field not used		*/
30*0Sstevel@tonic-gate     short		timezone;
31*0Sstevel@tonic-gate     short		dstflag;	/* Field not used		*/
32*0Sstevel@tonic-gate };
33*0Sstevel@tonic-gate #include <time.h>
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include <locale.h>
36*0Sstevel@tonic-gate #include <string.h>
37*0Sstevel@tonic-gate #include <stdlib.h>
38*0Sstevel@tonic-gate #include <note.h>
39*0Sstevel@tonic-gate #include <libintl.h>
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate #if	!defined(lint) && !defined(SABER)
42*0Sstevel@tonic-gate static char RCS[] =
43*0Sstevel@tonic-gate 	"$Header: /home/laramie/berliner/ws/backup/usr/src/cmd/backup/lib/getdate.y,v 1.5 1992/06/09 21:46:21 sam Exp $";
44*0Sstevel@tonic-gate #endif	/* !defined(lint) && !defined(SABER) */
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate #define EPOCH		1970
48*0Sstevel@tonic-gate #define HOURN(x)	(x * 60)
49*0Sstevel@tonic-gate #define SECSPERDAY	(24L * 60L * 60L)
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate #define CHECK_TM(y) (((y) % 100) < 70 ? (y) + 2000 : (y) + 1900)
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate /*
54*0Sstevel@tonic-gate **  An entry in the lexical lookup table.
55*0Sstevel@tonic-gate */
56*0Sstevel@tonic-gate typedef struct _TABLE {
57*0Sstevel@tonic-gate     char	*name;
58*0Sstevel@tonic-gate     int		type;
59*0Sstevel@tonic-gate     time_t	value;
60*0Sstevel@tonic-gate } TABLE;
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate /*
64*0Sstevel@tonic-gate **  Daylight-savings mode:  on, off, or not yet known.
65*0Sstevel@tonic-gate */
66*0Sstevel@tonic-gate typedef enum _DSTMODE {
67*0Sstevel@tonic-gate     DSTon, DSToff, DSTmaybe
68*0Sstevel@tonic-gate } DSTMODE;
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate /*
71*0Sstevel@tonic-gate **  Meridian:  am, pm, or 24-hour style.
72*0Sstevel@tonic-gate */
73*0Sstevel@tonic-gate typedef enum _MERIDIAN {
74*0Sstevel@tonic-gate     MERam, MERpm, MER24
75*0Sstevel@tonic-gate } MERIDIAN;
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate /*
79*0Sstevel@tonic-gate **  Global variables.  We could get rid of most of these by using a good
80*0Sstevel@tonic-gate **  union as the yacc stack.  (This routine was originally written before
81*0Sstevel@tonic-gate **  yacc had the %union construct.)  Maybe someday; right now we only use
82*0Sstevel@tonic-gate **  the %union very rarely.
83*0Sstevel@tonic-gate */
84*0Sstevel@tonic-gate static char	*yyInput;
85*0Sstevel@tonic-gate static DSTMODE	yyDSTmode;
86*0Sstevel@tonic-gate static time_t	yyDayOrdinal;
87*0Sstevel@tonic-gate static time_t	yyDayNumber;
88*0Sstevel@tonic-gate static int	yyHaveDate;
89*0Sstevel@tonic-gate static int	yyHaveDay;
90*0Sstevel@tonic-gate static int	yyHaveRel;
91*0Sstevel@tonic-gate static int	yyHaveTime;
92*0Sstevel@tonic-gate static int	yyHaveZone;
93*0Sstevel@tonic-gate static time_t	yyTimezone;
94*0Sstevel@tonic-gate static time_t	yyDay;
95*0Sstevel@tonic-gate static time_t	yyHour;
96*0Sstevel@tonic-gate static time_t	yyMinutes;
97*0Sstevel@tonic-gate static time_t	yyMonth;
98*0Sstevel@tonic-gate static time_t	yySeconds;
99*0Sstevel@tonic-gate static time_t	yyYear;
100*0Sstevel@tonic-gate static MERIDIAN	yyMeridian;
101*0Sstevel@tonic-gate static time_t	yyRelMonth;
102*0Sstevel@tonic-gate static time_t	yyRelSeconds;
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate static char	*domainname = "hsm_libdump";	/* for dgettext() */
105*0Sstevel@tonic-gate 
106*0Sstevel@tonic-gate #define yylex 1					/* suppress yacc's definition */
107*0Sstevel@tonic-gate %}
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate %union {
110*0Sstevel@tonic-gate     time_t		Number;
111*0Sstevel@tonic-gate     enum _MERIDIAN	Meridian;
112*0Sstevel@tonic-gate }
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate %token	tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
115*0Sstevel@tonic-gate %token	tSEC_UNIT tSNUMBER tUNUMBER tZONE
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate %type	<Number>	tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
118*0Sstevel@tonic-gate %type	<Number>	tSEC_UNIT tSNUMBER tUNUMBER tZONE
119*0Sstevel@tonic-gate %type	<Meridian>	tMERIDIAN o_merid
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate %%
122*0Sstevel@tonic-gate 
123*0Sstevel@tonic-gate spec	: /* NULL */
124*0Sstevel@tonic-gate 	| spec item
125*0Sstevel@tonic-gate 	;
126*0Sstevel@tonic-gate 
127*0Sstevel@tonic-gate item	: time {
128*0Sstevel@tonic-gate 	    yyHaveTime++;
129*0Sstevel@tonic-gate 	}
130*0Sstevel@tonic-gate 	| zone {
131*0Sstevel@tonic-gate 	    yyHaveZone++;
132*0Sstevel@tonic-gate 	}
133*0Sstevel@tonic-gate 	| date {
134*0Sstevel@tonic-gate 	    yyHaveDate++;
135*0Sstevel@tonic-gate 	}
136*0Sstevel@tonic-gate 	| day {
137*0Sstevel@tonic-gate 	    yyHaveDay++;
138*0Sstevel@tonic-gate 	}
139*0Sstevel@tonic-gate 	| rel {
140*0Sstevel@tonic-gate 	    yyHaveRel++;
141*0Sstevel@tonic-gate 	}
142*0Sstevel@tonic-gate 	| number
143*0Sstevel@tonic-gate 	;
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate time	: tUNUMBER tMERIDIAN {
146*0Sstevel@tonic-gate 	    yyHour = $1;
147*0Sstevel@tonic-gate 	    yyMinutes = 0;
148*0Sstevel@tonic-gate 	    yySeconds = 0;
149*0Sstevel@tonic-gate 	    yyMeridian = $2;
150*0Sstevel@tonic-gate 	}
151*0Sstevel@tonic-gate 	| tUNUMBER ':' tUNUMBER o_merid {
152*0Sstevel@tonic-gate 	    yyHour = $1;
153*0Sstevel@tonic-gate 	    yyMinutes = $3;
154*0Sstevel@tonic-gate 	    yySeconds = 0;
155*0Sstevel@tonic-gate 	    yyMeridian = $4;
156*0Sstevel@tonic-gate 	}
157*0Sstevel@tonic-gate 	| tUNUMBER ':' tUNUMBER tSNUMBER {
158*0Sstevel@tonic-gate 	    yyHour = $1;
159*0Sstevel@tonic-gate 	    yyMinutes = $3;
160*0Sstevel@tonic-gate 	    yyMeridian = MER24;
161*0Sstevel@tonic-gate 	    yyDSTmode = DSToff;
162*0Sstevel@tonic-gate 	    yyTimezone = - ($4 % 100 + ($4 / 100) * 60);
163*0Sstevel@tonic-gate 	}
164*0Sstevel@tonic-gate 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid {
165*0Sstevel@tonic-gate 	    yyHour = $1;
166*0Sstevel@tonic-gate 	    yyMinutes = $3;
167*0Sstevel@tonic-gate 	    yySeconds = $5;
168*0Sstevel@tonic-gate 	    yyMeridian = $6;
169*0Sstevel@tonic-gate 	}
170*0Sstevel@tonic-gate 	| tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER {
171*0Sstevel@tonic-gate 	    yyHour = $1;
172*0Sstevel@tonic-gate 	    yyMinutes = $3;
173*0Sstevel@tonic-gate 	    yySeconds = $5;
174*0Sstevel@tonic-gate 	    yyMeridian = MER24;
175*0Sstevel@tonic-gate 	    yyDSTmode = DSToff;
176*0Sstevel@tonic-gate 	    yyTimezone = - ($6 % 100 + ($6 / 100) * 60);
177*0Sstevel@tonic-gate 	}
178*0Sstevel@tonic-gate 	;
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate zone	: tZONE {
181*0Sstevel@tonic-gate 	    yyTimezone = $1;
182*0Sstevel@tonic-gate 	    yyDSTmode = DSToff;
183*0Sstevel@tonic-gate 	}
184*0Sstevel@tonic-gate 	| tDAYZONE {
185*0Sstevel@tonic-gate 	    yyTimezone = $1;
186*0Sstevel@tonic-gate 	    yyDSTmode = DSTon;
187*0Sstevel@tonic-gate 	}
188*0Sstevel@tonic-gate 	;
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate day	: tDAY {
191*0Sstevel@tonic-gate 	    yyDayOrdinal = 1;
192*0Sstevel@tonic-gate 	    yyDayNumber = $1;
193*0Sstevel@tonic-gate 	}
194*0Sstevel@tonic-gate 	| tDAY ',' {
195*0Sstevel@tonic-gate 	    yyDayOrdinal = 1;
196*0Sstevel@tonic-gate 	    yyDayNumber = $1;
197*0Sstevel@tonic-gate 	}
198*0Sstevel@tonic-gate 	| tUNUMBER tDAY {
199*0Sstevel@tonic-gate 	    yyDayOrdinal = $1;
200*0Sstevel@tonic-gate 	    yyDayNumber = $2;
201*0Sstevel@tonic-gate 	}
202*0Sstevel@tonic-gate 	;
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate date	: tUNUMBER '/' tUNUMBER {
205*0Sstevel@tonic-gate 	    yyMonth = $1;
206*0Sstevel@tonic-gate 	    yyDay = $3;
207*0Sstevel@tonic-gate 	}
208*0Sstevel@tonic-gate 	| tUNUMBER '/' tUNUMBER '/' tUNUMBER {
209*0Sstevel@tonic-gate 	    yyMonth = $1;
210*0Sstevel@tonic-gate 	    yyDay = $3;
211*0Sstevel@tonic-gate 	    yyYear = $5;
212*0Sstevel@tonic-gate 	}
213*0Sstevel@tonic-gate 	| tMONTH tUNUMBER {
214*0Sstevel@tonic-gate 	    yyMonth = $1;
215*0Sstevel@tonic-gate 	    yyDay = $2;
216*0Sstevel@tonic-gate 	}
217*0Sstevel@tonic-gate 	| tMONTH tUNUMBER ',' tUNUMBER {
218*0Sstevel@tonic-gate 	    yyMonth = $1;
219*0Sstevel@tonic-gate 	    yyDay = $2;
220*0Sstevel@tonic-gate 	    yyYear = $4;
221*0Sstevel@tonic-gate 	}
222*0Sstevel@tonic-gate 	| tUNUMBER tMONTH {
223*0Sstevel@tonic-gate 	    yyMonth = $2;
224*0Sstevel@tonic-gate 	    yyDay = $1;
225*0Sstevel@tonic-gate 	}
226*0Sstevel@tonic-gate 	| tUNUMBER tMONTH tUNUMBER {
227*0Sstevel@tonic-gate 	    yyMonth = $2;
228*0Sstevel@tonic-gate 	    yyDay = $1;
229*0Sstevel@tonic-gate 	    yyYear = $3;
230*0Sstevel@tonic-gate 	}
231*0Sstevel@tonic-gate 	;
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate rel	: relunit tAGO {
234*0Sstevel@tonic-gate 	    yyRelSeconds = -yyRelSeconds;
235*0Sstevel@tonic-gate 	    yyRelMonth = -yyRelMonth;
236*0Sstevel@tonic-gate 	}
237*0Sstevel@tonic-gate 	| relunit
238*0Sstevel@tonic-gate 	;
239*0Sstevel@tonic-gate 
240*0Sstevel@tonic-gate relunit	: tUNUMBER tMINUTE_UNIT {
241*0Sstevel@tonic-gate 	    yyRelSeconds += $1 * $2 * 60L;
242*0Sstevel@tonic-gate 	}
243*0Sstevel@tonic-gate 	| tSNUMBER tMINUTE_UNIT {
244*0Sstevel@tonic-gate 	    yyRelSeconds += $1 * $2 * 60L;
245*0Sstevel@tonic-gate 	}
246*0Sstevel@tonic-gate 	| tMINUTE_UNIT {
247*0Sstevel@tonic-gate 	    yyRelSeconds += $1 * 60L;
248*0Sstevel@tonic-gate 	}
249*0Sstevel@tonic-gate 	| tSNUMBER tSEC_UNIT {
250*0Sstevel@tonic-gate 	    yyRelSeconds += $1;
251*0Sstevel@tonic-gate 	}
252*0Sstevel@tonic-gate 	| tUNUMBER tSEC_UNIT {
253*0Sstevel@tonic-gate 	    yyRelSeconds += $1;
254*0Sstevel@tonic-gate 	}
255*0Sstevel@tonic-gate 	| tSEC_UNIT {
256*0Sstevel@tonic-gate 	    yyRelSeconds++;
257*0Sstevel@tonic-gate 	}
258*0Sstevel@tonic-gate 	| tSNUMBER tMONTH_UNIT {
259*0Sstevel@tonic-gate 	    yyRelMonth += $1 * $2;
260*0Sstevel@tonic-gate 	}
261*0Sstevel@tonic-gate 	| tUNUMBER tMONTH_UNIT {
262*0Sstevel@tonic-gate 	    yyRelMonth += $1 * $2;
263*0Sstevel@tonic-gate 	}
264*0Sstevel@tonic-gate 	| tMONTH_UNIT {
265*0Sstevel@tonic-gate 	    yyRelMonth += $1;
266*0Sstevel@tonic-gate 	}
267*0Sstevel@tonic-gate 	;
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate number	: tUNUMBER {
270*0Sstevel@tonic-gate 	    if (yyHaveTime && yyHaveDate && !yyHaveRel)
271*0Sstevel@tonic-gate 		yyYear = $1;
272*0Sstevel@tonic-gate 	    else {
273*0Sstevel@tonic-gate 		yyHaveTime++;
274*0Sstevel@tonic-gate 		if ($1 < 100) {
275*0Sstevel@tonic-gate 		    yyHour = $1;
276*0Sstevel@tonic-gate 		    yyMinutes = 0;
277*0Sstevel@tonic-gate 		}
278*0Sstevel@tonic-gate 		else {
279*0Sstevel@tonic-gate 		    yyHour = $1 / 100;
280*0Sstevel@tonic-gate 		    yyMinutes = $1 % 100;
281*0Sstevel@tonic-gate 		}
282*0Sstevel@tonic-gate 		yySeconds = 0;
283*0Sstevel@tonic-gate 		yyMeridian = MER24;
284*0Sstevel@tonic-gate 	    }
285*0Sstevel@tonic-gate 	}
286*0Sstevel@tonic-gate 	;
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate o_merid	: /* NULL */ {
289*0Sstevel@tonic-gate 	    $$ = MER24;
290*0Sstevel@tonic-gate 	}
291*0Sstevel@tonic-gate 	| tMERIDIAN {
292*0Sstevel@tonic-gate 	    $$ = $1;
293*0Sstevel@tonic-gate 	}
294*0Sstevel@tonic-gate 	;
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate %%
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate /* Month and day table. */
299*0Sstevel@tonic-gate static TABLE	MonthDayTable[] = {
300*0Sstevel@tonic-gate     { "january",	tMONTH,  1 },
301*0Sstevel@tonic-gate     { "february",	tMONTH,  2 },
302*0Sstevel@tonic-gate     { "march",		tMONTH,  3 },
303*0Sstevel@tonic-gate     { "april",		tMONTH,  4 },
304*0Sstevel@tonic-gate     { "may",		tMONTH,  5 },
305*0Sstevel@tonic-gate     { "june",		tMONTH,  6 },
306*0Sstevel@tonic-gate     { "july",		tMONTH,  7 },
307*0Sstevel@tonic-gate     { "august",		tMONTH,  8 },
308*0Sstevel@tonic-gate     { "september",	tMONTH,  9 },
309*0Sstevel@tonic-gate     { "sept",		tMONTH,  9 },
310*0Sstevel@tonic-gate     { "october",	tMONTH, 10 },
311*0Sstevel@tonic-gate     { "november",	tMONTH, 11 },
312*0Sstevel@tonic-gate     { "december",	tMONTH, 12 },
313*0Sstevel@tonic-gate     { "sunday",		tDAY, 0 },
314*0Sstevel@tonic-gate     { "monday",		tDAY, 1 },
315*0Sstevel@tonic-gate     { "tuesday",	tDAY, 2 },
316*0Sstevel@tonic-gate     { "tues",		tDAY, 2 },
317*0Sstevel@tonic-gate     { "wednesday",	tDAY, 3 },
318*0Sstevel@tonic-gate     { "wednes",		tDAY, 3 },
319*0Sstevel@tonic-gate     { "thursday",	tDAY, 4 },
320*0Sstevel@tonic-gate     { "thur",		tDAY, 4 },
321*0Sstevel@tonic-gate     { "thurs",		tDAY, 4 },
322*0Sstevel@tonic-gate     { "friday",		tDAY, 5 },
323*0Sstevel@tonic-gate     { "saturday",	tDAY, 6 },
324*0Sstevel@tonic-gate     { NULL }
325*0Sstevel@tonic-gate };
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate /* Time units table. */
328*0Sstevel@tonic-gate static TABLE	UnitsTable[] = {
329*0Sstevel@tonic-gate     { "year",		tMONTH_UNIT,	12 },
330*0Sstevel@tonic-gate     { "month",		tMONTH_UNIT,	1 },
331*0Sstevel@tonic-gate     { "fortnight",	tMINUTE_UNIT,	14 * 24 * 60 },
332*0Sstevel@tonic-gate     { "week",		tMINUTE_UNIT,	7 * 24 * 60 },
333*0Sstevel@tonic-gate     { "day",		tMINUTE_UNIT,	1 * 24 * 60 },
334*0Sstevel@tonic-gate     { "hour",		tMINUTE_UNIT,	60 },
335*0Sstevel@tonic-gate     { "minute",		tMINUTE_UNIT,	1 },
336*0Sstevel@tonic-gate     { "min",		tMINUTE_UNIT,	1 },
337*0Sstevel@tonic-gate     { "second",		tSEC_UNIT,	1 },
338*0Sstevel@tonic-gate     { "sec",		tSEC_UNIT,	1 },
339*0Sstevel@tonic-gate     { NULL }
340*0Sstevel@tonic-gate };
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate /* Assorted relative-time words. */
343*0Sstevel@tonic-gate static TABLE	OtherTable[] = {
344*0Sstevel@tonic-gate     { "tomorrow",	tMINUTE_UNIT,	1 * 24 * 60 },
345*0Sstevel@tonic-gate     { "yesterday",	tMINUTE_UNIT,	-1 * 24 * 60 },
346*0Sstevel@tonic-gate     { "today",		tMINUTE_UNIT,	0 },
347*0Sstevel@tonic-gate     { "now",		tMINUTE_UNIT,	0 },
348*0Sstevel@tonic-gate     { "last",		tUNUMBER,	-1 },
349*0Sstevel@tonic-gate     { "this",		tMINUTE_UNIT,	0 },
350*0Sstevel@tonic-gate     { "next",		tUNUMBER,	2 },
351*0Sstevel@tonic-gate     { "first",		tUNUMBER,	1 },
352*0Sstevel@tonic-gate /*  { "second",		tUNUMBER,	2 }, */
353*0Sstevel@tonic-gate     { "third",		tUNUMBER,	3 },
354*0Sstevel@tonic-gate     { "fourth",		tUNUMBER,	4 },
355*0Sstevel@tonic-gate     { "fifth",		tUNUMBER,	5 },
356*0Sstevel@tonic-gate     { "sixth",		tUNUMBER,	6 },
357*0Sstevel@tonic-gate     { "seventh",	tUNUMBER,	7 },
358*0Sstevel@tonic-gate     { "eighth",		tUNUMBER,	8 },
359*0Sstevel@tonic-gate     { "ninth",		tUNUMBER,	9 },
360*0Sstevel@tonic-gate     { "tenth",		tUNUMBER,	10 },
361*0Sstevel@tonic-gate     { "eleventh",	tUNUMBER,	11 },
362*0Sstevel@tonic-gate     { "twelfth",	tUNUMBER,	12 },
363*0Sstevel@tonic-gate     { "ago",		tAGO,	1 },
364*0Sstevel@tonic-gate     { NULL }
365*0Sstevel@tonic-gate };
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate /* The timezone table. */
368*0Sstevel@tonic-gate static TABLE	TimezoneTable[] = {
369*0Sstevel@tonic-gate     { "gmt",	tZONE,     HOURN( 0) },	/* Greenwich Mean */
370*0Sstevel@tonic-gate     { "ut",	tZONE,     HOURN( 0) },	/* Universal (Coordinated) */
371*0Sstevel@tonic-gate     { "utc",	tZONE,     HOURN( 0) },
372*0Sstevel@tonic-gate     { "wet",	tZONE,     HOURN( 0) },	/* Western European */
373*0Sstevel@tonic-gate     { "bst",	tDAYZONE,  HOURN( 0) },	/* British Summer */
374*0Sstevel@tonic-gate     { "wat",	tZONE,     HOURN( 1) },	/* West Africa */
375*0Sstevel@tonic-gate     { "at",	tZONE,     HOURN( 2) },	/* Azores */
376*0Sstevel@tonic-gate #if	0
377*0Sstevel@tonic-gate     /* For completeness.  BST is also British Summer, and GST is
378*0Sstevel@tonic-gate      * also Guam Standard. */
379*0Sstevel@tonic-gate     { "bst",	tZONE,     HOURN( 3) },	/* Brazil Standard */
380*0Sstevel@tonic-gate     { "gst",	tZONE,     HOURN( 3) },	/* Greenland Standard */
381*0Sstevel@tonic-gate #endif
382*0Sstevel@tonic-gate     { "nft",	tZONE,     HOURN(3.5) },	/* Newfoundland */
383*0Sstevel@tonic-gate     { "nst",	tZONE,     HOURN(3.5) },	/* Newfoundland Standard */
384*0Sstevel@tonic-gate     { "ndt",	tDAYZONE,  HOURN(3.5) },	/* Newfoundland Daylight */
385*0Sstevel@tonic-gate     { "ast",	tZONE,     HOURN( 4) },	/* Atlantic Standard */
386*0Sstevel@tonic-gate     { "adt",	tDAYZONE,  HOURN( 4) },	/* Atlantic Daylight */
387*0Sstevel@tonic-gate     { "est",	tZONE,     HOURN( 5) },	/* Eastern Standard */
388*0Sstevel@tonic-gate     { "edt",	tDAYZONE,  HOURN( 5) },	/* Eastern Daylight */
389*0Sstevel@tonic-gate     { "cst",	tZONE,     HOURN( 6) },	/* Central Standard */
390*0Sstevel@tonic-gate     { "cdt",	tDAYZONE,  HOURN( 6) },	/* Central Daylight */
391*0Sstevel@tonic-gate     { "mst",	tZONE,     HOURN( 7) },	/* Mountain Standard */
392*0Sstevel@tonic-gate     { "mdt",	tDAYZONE,  HOURN( 7) },	/* Mountain Daylight */
393*0Sstevel@tonic-gate     { "pst",	tZONE,     HOURN( 8) },	/* Pacific Standard */
394*0Sstevel@tonic-gate     { "pdt",	tDAYZONE,  HOURN( 8) },	/* Pacific Daylight */
395*0Sstevel@tonic-gate     { "yst",	tZONE,     HOURN( 9) },	/* Yukon Standard */
396*0Sstevel@tonic-gate     { "ydt",	tDAYZONE,  HOURN( 9) },	/* Yukon Daylight */
397*0Sstevel@tonic-gate     { "hst",	tZONE,     HOURN(10) },	/* Hawaii Standard */
398*0Sstevel@tonic-gate     { "hdt",	tDAYZONE,  HOURN(10) },	/* Hawaii Daylight */
399*0Sstevel@tonic-gate     { "cat",	tZONE,     HOURN(10) },	/* Central Alaska */
400*0Sstevel@tonic-gate     { "ahst",	tZONE,     HOURN(10) },	/* Alaska-Hawaii Standard */
401*0Sstevel@tonic-gate     { "nt",	tZONE,     HOURN(11) },	/* Nome */
402*0Sstevel@tonic-gate     { "idlw",	tZONE,     HOURN(12) },	/* International Date Line West */
403*0Sstevel@tonic-gate     { "cet",	tZONE,     -HOURN(1) },	/* Central European */
404*0Sstevel@tonic-gate     { "met",	tZONE,     -HOURN(1) },	/* Middle European */
405*0Sstevel@tonic-gate     { "mewt",	tZONE,     -HOURN(1) },	/* Middle European Winter */
406*0Sstevel@tonic-gate     { "mest",	tDAYZONE,  -HOURN(1) },	/* Middle European Summer */
407*0Sstevel@tonic-gate     { "swt",	tZONE,     -HOURN(1) },	/* Swedish Winter */
408*0Sstevel@tonic-gate     { "sst",	tDAYZONE,  -HOURN(1) },	/* Swedish Summer */
409*0Sstevel@tonic-gate     { "fwt",	tZONE,     -HOURN(1) },	/* French Winter */
410*0Sstevel@tonic-gate     { "fst",	tDAYZONE,  -HOURN(1) },	/* French Summer */
411*0Sstevel@tonic-gate     { "eet",	tZONE,     -HOURN(2) },	/* Eastern Europe, USSR Zone 1 */
412*0Sstevel@tonic-gate     { "bt",	tZONE,     -HOURN(3) },	/* Baghdad, USSR Zone 2 */
413*0Sstevel@tonic-gate     { "it",	tZONE,     -HOURN(3.5) },/* Iran */
414*0Sstevel@tonic-gate     { "zp4",	tZONE,     -HOURN(4) },	/* USSR Zone 3 */
415*0Sstevel@tonic-gate     { "zp5",	tZONE,     -HOURN(5) },	/* USSR Zone 4 */
416*0Sstevel@tonic-gate     { "ist",	tZONE,     -HOURN(5.5) },/* Indian Standard */
417*0Sstevel@tonic-gate     { "zp6",	tZONE,     -HOURN(6) },	/* USSR Zone 5 */
418*0Sstevel@tonic-gate #if	0
419*0Sstevel@tonic-gate     /* For completeness.  NST is also Newfoundland Stanard, nad SST is
420*0Sstevel@tonic-gate      * also Swedish Summer. */
421*0Sstevel@tonic-gate     { "nst",	tZONE,     -HOURN(6.5) },/* North Sumatra */
422*0Sstevel@tonic-gate     { "sst",	tZONE,     -HOURN(7) },	/* South Sumatra, USSR Zone 6 */
423*0Sstevel@tonic-gate #endif	/* 0 */
424*0Sstevel@tonic-gate     { "wast",	tZONE,     -HOURN(7) },	/* West Australian Standard */
425*0Sstevel@tonic-gate     { "wadt",	tDAYZONE,  -HOURN(7) },	/* West Australian Daylight */
426*0Sstevel@tonic-gate     { "jt",	tZONE,     -HOURN(7.5) },/* Java (3pm in Cronusland!) */
427*0Sstevel@tonic-gate     { "cct",	tZONE,     -HOURN(8) },	/* China Coast, USSR Zone 7 */
428*0Sstevel@tonic-gate     { "jst",	tZONE,     -HOURN(9) },	/* Japan Standard, USSR Zone 8 */
429*0Sstevel@tonic-gate     { "cast",	tZONE,     -HOURN(9.5) },/* Central Australian Standard */
430*0Sstevel@tonic-gate     { "cadt",	tDAYZONE,  -HOURN(9.5) },/* Central Australian Daylight */
431*0Sstevel@tonic-gate     { "east",	tZONE,     -HOURN(10) },	/* Eastern Australian Standard */
432*0Sstevel@tonic-gate     { "eadt",	tDAYZONE,  -HOURN(10) },	/* Eastern Australian Daylight */
433*0Sstevel@tonic-gate     { "gst",	tZONE,     -HOURN(10) },	/* Guam Standard, USSR Zone 9 */
434*0Sstevel@tonic-gate     { "nzt",	tZONE,     -HOURN(12) },	/* New Zealand */
435*0Sstevel@tonic-gate     { "nzst",	tZONE,     -HOURN(12) },	/* New Zealand Standard */
436*0Sstevel@tonic-gate     { "nzdt",	tDAYZONE,  -HOURN(12) },	/* New Zealand Daylight */
437*0Sstevel@tonic-gate     { "idle",	tZONE,     -HOURN(12) },	/* International Date Line East */
438*0Sstevel@tonic-gate     {  NULL  }
439*0Sstevel@tonic-gate };
440*0Sstevel@tonic-gate 
441*0Sstevel@tonic-gate /* Military timezone table. */
442*0Sstevel@tonic-gate static TABLE	MilitaryTable[] = {
443*0Sstevel@tonic-gate     { "a",	tZONE,	HOURN(  1) },
444*0Sstevel@tonic-gate     { "b",	tZONE,	HOURN(  2) },
445*0Sstevel@tonic-gate     { "c",	tZONE,	HOURN(  3) },
446*0Sstevel@tonic-gate     { "d",	tZONE,	HOURN(  4) },
447*0Sstevel@tonic-gate     { "e",	tZONE,	HOURN(  5) },
448*0Sstevel@tonic-gate     { "f",	tZONE,	HOURN(  6) },
449*0Sstevel@tonic-gate     { "g",	tZONE,	HOURN(  7) },
450*0Sstevel@tonic-gate     { "h",	tZONE,	HOURN(  8) },
451*0Sstevel@tonic-gate     { "i",	tZONE,	HOURN(  9) },
452*0Sstevel@tonic-gate     { "k",	tZONE,	HOURN( 10) },
453*0Sstevel@tonic-gate     { "l",	tZONE,	HOURN( 11) },
454*0Sstevel@tonic-gate     { "m",	tZONE,	HOURN( 12) },
455*0Sstevel@tonic-gate     { "n",	tZONE,	HOURN(- 1) },
456*0Sstevel@tonic-gate     { "o",	tZONE,	HOURN(- 2) },
457*0Sstevel@tonic-gate     { "p",	tZONE,	HOURN(- 3) },
458*0Sstevel@tonic-gate     { "q",	tZONE,	HOURN(- 4) },
459*0Sstevel@tonic-gate     { "r",	tZONE,	HOURN(- 5) },
460*0Sstevel@tonic-gate     { "s",	tZONE,	HOURN(- 6) },
461*0Sstevel@tonic-gate     { "t",	tZONE,	HOURN(- 7) },
462*0Sstevel@tonic-gate     { "u",	tZONE,	HOURN(- 8) },
463*0Sstevel@tonic-gate     { "v",	tZONE,	HOURN(- 9) },
464*0Sstevel@tonic-gate     { "w",	tZONE,	HOURN(-10) },
465*0Sstevel@tonic-gate     { "x",	tZONE,	HOURN(-11) },
466*0Sstevel@tonic-gate     { "y",	tZONE,	HOURN(-12) },
467*0Sstevel@tonic-gate     { "z",	tZONE,	HOURN(  0) },
468*0Sstevel@tonic-gate     { NULL }
469*0Sstevel@tonic-gate };
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate 
472*0Sstevel@tonic-gate 
473*0Sstevel@tonic-gate 
474*0Sstevel@tonic-gate /* ARGSUSED */
475*0Sstevel@tonic-gate static void
476*0Sstevel@tonic-gate yyerror(s)
477*0Sstevel@tonic-gate     char	*s;
478*0Sstevel@tonic-gate {
479*0Sstevel@tonic-gate }
480*0Sstevel@tonic-gate 
481*0Sstevel@tonic-gate 
482*0Sstevel@tonic-gate static time_t
483*0Sstevel@tonic-gate ToSeconds(Hours, Minutes, Seconds, Meridian)
484*0Sstevel@tonic-gate     time_t	Hours;
485*0Sstevel@tonic-gate     time_t	Minutes;
486*0Sstevel@tonic-gate     time_t	Seconds;
487*0Sstevel@tonic-gate     MERIDIAN	Meridian;
488*0Sstevel@tonic-gate {
489*0Sstevel@tonic-gate     if (Minutes < 0 || Minutes > 59 || Seconds < 0 || Seconds > 59)
490*0Sstevel@tonic-gate 	return -1;
491*0Sstevel@tonic-gate     switch (Meridian) {
492*0Sstevel@tonic-gate     case MER24:
493*0Sstevel@tonic-gate 	if (Hours < 0 || Hours > 23)
494*0Sstevel@tonic-gate 	    return -1;
495*0Sstevel@tonic-gate 	return (Hours * 60L + Minutes) * 60L + Seconds;
496*0Sstevel@tonic-gate     case MERam:
497*0Sstevel@tonic-gate 	if (Hours < 1 || Hours > 12)
498*0Sstevel@tonic-gate 	    return -1;
499*0Sstevel@tonic-gate 	if (Hours != 12)
500*0Sstevel@tonic-gate 	    return (Hours * 60L + Minutes) * 60L + Seconds;
501*0Sstevel@tonic-gate 	else
502*0Sstevel@tonic-gate 	    return Minutes * 60L + Seconds;
503*0Sstevel@tonic-gate     case MERpm:
504*0Sstevel@tonic-gate 	if (Hours < 1 || Hours > 12)
505*0Sstevel@tonic-gate 	    return -1;
506*0Sstevel@tonic-gate 	if (Hours != 12)
507*0Sstevel@tonic-gate 	    return ((Hours + 12) * 60L + Minutes) * 60L + Seconds;
508*0Sstevel@tonic-gate 	else
509*0Sstevel@tonic-gate 	    return (720L + Minutes) * 60L + Seconds;
510*0Sstevel@tonic-gate     }
511*0Sstevel@tonic-gate     /* NOTREACHED */
512*0Sstevel@tonic-gate }
513*0Sstevel@tonic-gate 
514*0Sstevel@tonic-gate 
515*0Sstevel@tonic-gate static time_t
516*0Sstevel@tonic-gate Convert(Month, Day, Year, Hours, Minutes, Seconds, Meridian, DSTmode)
517*0Sstevel@tonic-gate     time_t	Month;
518*0Sstevel@tonic-gate     time_t	Day;
519*0Sstevel@tonic-gate     time_t	Year;
520*0Sstevel@tonic-gate     time_t	Hours;
521*0Sstevel@tonic-gate     time_t	Minutes;
522*0Sstevel@tonic-gate     time_t	Seconds;
523*0Sstevel@tonic-gate     MERIDIAN	Meridian;
524*0Sstevel@tonic-gate     DSTMODE	DSTmode;
525*0Sstevel@tonic-gate {
526*0Sstevel@tonic-gate     static int	DaysInMonth[12] = {
527*0Sstevel@tonic-gate 	31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
528*0Sstevel@tonic-gate     };
529*0Sstevel@tonic-gate     time_t	tod;
530*0Sstevel@tonic-gate     time_t	Julian;
531*0Sstevel@tonic-gate     time_t	i;
532*0Sstevel@tonic-gate 
533*0Sstevel@tonic-gate     if (Year < 0)
534*0Sstevel@tonic-gate 	Year = -Year;
535*0Sstevel@tonic-gate     if (Year < 138)
536*0Sstevel@tonic-gate 	Year += 1900;
537*0Sstevel@tonic-gate     DaysInMonth[1] = Year % 4 == 0 && (Year % 100 != 0 || Year % 400 == 0)
538*0Sstevel@tonic-gate 		    ? 29 : 28;
539*0Sstevel@tonic-gate     if (Year < EPOCH || Year > 2037
540*0Sstevel@tonic-gate      || Month < 1 || Month > 12
541*0Sstevel@tonic-gate      /* LINTED Month is a time_t so intermediate results aren't truncated */
542*0Sstevel@tonic-gate      || Day < 1 || Day > DaysInMonth[(int)--Month])
543*0Sstevel@tonic-gate 	return -1;
544*0Sstevel@tonic-gate 
545*0Sstevel@tonic-gate     for (Julian = Day - 1, i = 0; i < Month; i++)
546*0Sstevel@tonic-gate 	Julian += DaysInMonth[i];
547*0Sstevel@tonic-gate     for (i = EPOCH; i < Year; i++)
548*0Sstevel@tonic-gate 	Julian += 365 + (i % 4 == 0);
549*0Sstevel@tonic-gate     Julian *= SECSPERDAY;
550*0Sstevel@tonic-gate     Julian += yyTimezone * 60L;
551*0Sstevel@tonic-gate     if ((tod = ToSeconds(Hours, Minutes, Seconds, Meridian)) < 0)
552*0Sstevel@tonic-gate 	return -1;
553*0Sstevel@tonic-gate     Julian += tod;
554*0Sstevel@tonic-gate     if (DSTmode == DSTon
555*0Sstevel@tonic-gate      || (DSTmode == DSTmaybe && localtime(&Julian)->tm_isdst))
556*0Sstevel@tonic-gate 	Julian -= 60 * 60;
557*0Sstevel@tonic-gate     return Julian;
558*0Sstevel@tonic-gate }
559*0Sstevel@tonic-gate 
560*0Sstevel@tonic-gate 
561*0Sstevel@tonic-gate static time_t
562*0Sstevel@tonic-gate DSTcorrect(Start, Future)
563*0Sstevel@tonic-gate     time_t	Start;
564*0Sstevel@tonic-gate     time_t	Future;
565*0Sstevel@tonic-gate {
566*0Sstevel@tonic-gate     time_t	StartDay;
567*0Sstevel@tonic-gate     time_t	FutureDay;
568*0Sstevel@tonic-gate 
569*0Sstevel@tonic-gate     StartDay = (localtime(&Start)->tm_hour + 1) % 24;
570*0Sstevel@tonic-gate     FutureDay = (localtime(&Future)->tm_hour + 1) % 24;
571*0Sstevel@tonic-gate     return (Future - Start) + (StartDay - FutureDay) * 60L * 60L;
572*0Sstevel@tonic-gate }
573*0Sstevel@tonic-gate 
574*0Sstevel@tonic-gate 
575*0Sstevel@tonic-gate static time_t
576*0Sstevel@tonic-gate RelativeDate(Start, DayOrdinal, DayNumber)
577*0Sstevel@tonic-gate     time_t	Start;
578*0Sstevel@tonic-gate     time_t	DayOrdinal;
579*0Sstevel@tonic-gate     time_t	DayNumber;
580*0Sstevel@tonic-gate {
581*0Sstevel@tonic-gate     struct tm	*tm;
582*0Sstevel@tonic-gate     time_t	now;
583*0Sstevel@tonic-gate 
584*0Sstevel@tonic-gate     now = Start;
585*0Sstevel@tonic-gate     tm = localtime(&now);
586*0Sstevel@tonic-gate     now += SECSPERDAY * ((DayNumber - tm->tm_wday + 7) % 7);
587*0Sstevel@tonic-gate     now += 7 * SECSPERDAY * (DayOrdinal <= 0 ? DayOrdinal : DayOrdinal - 1);
588*0Sstevel@tonic-gate     return DSTcorrect(Start, now);
589*0Sstevel@tonic-gate }
590*0Sstevel@tonic-gate 
591*0Sstevel@tonic-gate 
592*0Sstevel@tonic-gate static time_t
593*0Sstevel@tonic-gate RelativeMonth(Start, RelMonth)
594*0Sstevel@tonic-gate     time_t	Start;
595*0Sstevel@tonic-gate     time_t	RelMonth;
596*0Sstevel@tonic-gate {
597*0Sstevel@tonic-gate     struct tm	*tm;
598*0Sstevel@tonic-gate     time_t	Month;
599*0Sstevel@tonic-gate     time_t	Year;
600*0Sstevel@tonic-gate 
601*0Sstevel@tonic-gate     if (RelMonth == 0)
602*0Sstevel@tonic-gate 	return 0;
603*0Sstevel@tonic-gate     tm = localtime(&Start);
604*0Sstevel@tonic-gate     Month = 12 * tm->tm_year + tm->tm_mon + RelMonth;
605*0Sstevel@tonic-gate     Year = Month / 12;
606*0Sstevel@tonic-gate     Month = Month % 12 + 1;
607*0Sstevel@tonic-gate     return DSTcorrect(Start,
608*0Sstevel@tonic-gate 	    Convert(Month, (time_t)tm->tm_mday, Year,
609*0Sstevel@tonic-gate 		(time_t)tm->tm_hour, (time_t)tm->tm_min, (time_t)tm->tm_sec,
610*0Sstevel@tonic-gate 		MER24, DSTmaybe));
611*0Sstevel@tonic-gate }
612*0Sstevel@tonic-gate 
613*0Sstevel@tonic-gate 
614*0Sstevel@tonic-gate static int
615*0Sstevel@tonic-gate LookupWord(buff)
616*0Sstevel@tonic-gate     char		*buff;
617*0Sstevel@tonic-gate {
618*0Sstevel@tonic-gate     char	*p;
619*0Sstevel@tonic-gate     char	*q;
620*0Sstevel@tonic-gate     TABLE	*tp;
621*0Sstevel@tonic-gate     uint_t	i;
622*0Sstevel@tonic-gate     int		abbrev;
623*0Sstevel@tonic-gate 
624*0Sstevel@tonic-gate     /* Make it lowercase. */
625*0Sstevel@tonic-gate     for (p = buff; *p; p++)
626*0Sstevel@tonic-gate 	if (isupper((u_char)*p))
627*0Sstevel@tonic-gate 	    *p = tolower(*p);
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate     if (strcmp(buff, "am") == 0 || strcmp(buff, "a.m.") == 0) {
630*0Sstevel@tonic-gate 	yylval.Meridian = MERam;
631*0Sstevel@tonic-gate 	return tMERIDIAN;
632*0Sstevel@tonic-gate     }
633*0Sstevel@tonic-gate     if (strcmp(buff, "pm") == 0 || strcmp(buff, "p.m.") == 0) {
634*0Sstevel@tonic-gate 	yylval.Meridian = MERpm;
635*0Sstevel@tonic-gate 	return tMERIDIAN;
636*0Sstevel@tonic-gate     }
637*0Sstevel@tonic-gate 
638*0Sstevel@tonic-gate     /* See if we have an abbreviation for a month. */
639*0Sstevel@tonic-gate     if (strlen(buff) == 3)
640*0Sstevel@tonic-gate 	abbrev = 1;
641*0Sstevel@tonic-gate     else if (strlen(buff) == 4 && buff[3] == '.') {
642*0Sstevel@tonic-gate 	abbrev = 1;
643*0Sstevel@tonic-gate 	buff[3] = '\0';
644*0Sstevel@tonic-gate     }
645*0Sstevel@tonic-gate     else
646*0Sstevel@tonic-gate 	abbrev = 0;
647*0Sstevel@tonic-gate 
648*0Sstevel@tonic-gate     for (tp = MonthDayTable; tp->name; tp++) {
649*0Sstevel@tonic-gate 	if (abbrev) {
650*0Sstevel@tonic-gate 	    if (strncmp(buff, tp->name, 3) == 0) {
651*0Sstevel@tonic-gate 		yylval.Number = tp->value;
652*0Sstevel@tonic-gate 		return tp->type;
653*0Sstevel@tonic-gate 	    }
654*0Sstevel@tonic-gate 	}
655*0Sstevel@tonic-gate 	else if (strcmp(buff, tp->name) == 0) {
656*0Sstevel@tonic-gate 	    yylval.Number = tp->value;
657*0Sstevel@tonic-gate 	    return tp->type;
658*0Sstevel@tonic-gate 	}
659*0Sstevel@tonic-gate     }
660*0Sstevel@tonic-gate 
661*0Sstevel@tonic-gate     for (tp = TimezoneTable; tp->name; tp++)
662*0Sstevel@tonic-gate 	if (strcmp(buff, tp->name) == 0) {
663*0Sstevel@tonic-gate 	    yylval.Number = tp->value;
664*0Sstevel@tonic-gate 	    return tp->type;
665*0Sstevel@tonic-gate 	}
666*0Sstevel@tonic-gate 
667*0Sstevel@tonic-gate     for (tp = UnitsTable; tp->name; tp++)
668*0Sstevel@tonic-gate 	if (strcmp(buff, tp->name) == 0) {
669*0Sstevel@tonic-gate 	    yylval.Number = tp->value;
670*0Sstevel@tonic-gate 	    return tp->type;
671*0Sstevel@tonic-gate 	}
672*0Sstevel@tonic-gate 
673*0Sstevel@tonic-gate     /* Strip off any plural and try the units table again. */
674*0Sstevel@tonic-gate     i = strlen(buff) - 1;
675*0Sstevel@tonic-gate     if (buff[i] == 's') {
676*0Sstevel@tonic-gate 	buff[i] = '\0';
677*0Sstevel@tonic-gate 	for (tp = UnitsTable; tp->name; tp++)
678*0Sstevel@tonic-gate 	    if (strcmp(buff, tp->name) == 0) {
679*0Sstevel@tonic-gate 		yylval.Number = tp->value;
680*0Sstevel@tonic-gate 		return tp->type;
681*0Sstevel@tonic-gate 	    }
682*0Sstevel@tonic-gate     }
683*0Sstevel@tonic-gate 
684*0Sstevel@tonic-gate     for (tp = OtherTable; tp->name; tp++)
685*0Sstevel@tonic-gate 	if (strcmp(buff, tp->name) == 0) {
686*0Sstevel@tonic-gate 	    yylval.Number = tp->value;
687*0Sstevel@tonic-gate 	    return tp->type;
688*0Sstevel@tonic-gate 	}
689*0Sstevel@tonic-gate 
690*0Sstevel@tonic-gate     /* Military timezones. */
691*0Sstevel@tonic-gate     if (buff[1] == '\0' && isalpha((u_char)*buff)) {
692*0Sstevel@tonic-gate 	for (tp = MilitaryTable; tp->name; tp++)
693*0Sstevel@tonic-gate 	    if (strcmp(buff, tp->name) == 0) {
694*0Sstevel@tonic-gate 		yylval.Number = tp->value;
695*0Sstevel@tonic-gate 		return tp->type;
696*0Sstevel@tonic-gate 	    }
697*0Sstevel@tonic-gate     }
698*0Sstevel@tonic-gate 
699*0Sstevel@tonic-gate     /* Drop out any periods and try the timezone table again. */
700*0Sstevel@tonic-gate     for (i = 0, p = q = buff; *q; q++)
701*0Sstevel@tonic-gate 	if (*q != '.')
702*0Sstevel@tonic-gate 	    *p++ = *q;
703*0Sstevel@tonic-gate 	else
704*0Sstevel@tonic-gate 	    i++;
705*0Sstevel@tonic-gate     *p = '\0';
706*0Sstevel@tonic-gate     if (i)
707*0Sstevel@tonic-gate 	for (tp = TimezoneTable; tp->name; tp++)
708*0Sstevel@tonic-gate 	    if (strcmp(buff, tp->name) == 0) {
709*0Sstevel@tonic-gate 		yylval.Number = tp->value;
710*0Sstevel@tonic-gate 		return tp->type;
711*0Sstevel@tonic-gate 	    }
712*0Sstevel@tonic-gate 
713*0Sstevel@tonic-gate     return tID;
714*0Sstevel@tonic-gate }
715*0Sstevel@tonic-gate 
716*0Sstevel@tonic-gate void
717*0Sstevel@tonic-gate pdateerr(p)
718*0Sstevel@tonic-gate     char	*p;
719*0Sstevel@tonic-gate {
720*0Sstevel@tonic-gate     char	*name = "DATEMSK";	/* env variable for date format */
721*0Sstevel@tonic-gate     char	*value;
722*0Sstevel@tonic-gate     char	fmt[256], line[256];
723*0Sstevel@tonic-gate     FILE	*fp;
724*0Sstevel@tonic-gate     time_t	now;
725*0Sstevel@tonic-gate     struct tm	*tm;
726*0Sstevel@tonic-gate 
727*0Sstevel@tonic-gate     value = getenv(name);
728*0Sstevel@tonic-gate     if (value == (char *)0) {
729*0Sstevel@tonic-gate 	fprintf(stderr,
730*0Sstevel@tonic-gate 	    dgettext(domainname, "%s: Environment variable %s not set\n"),
731*0Sstevel@tonic-gate 		p, name);
732*0Sstevel@tonic-gate 	return;
733*0Sstevel@tonic-gate     }
734*0Sstevel@tonic-gate     switch (getdate_err) {
735*0Sstevel@tonic-gate 	case 0:
736*0Sstevel@tonic-gate 	default:
737*0Sstevel@tonic-gate 	    fprintf(stderr,
738*0Sstevel@tonic-gate 		dgettext(domainname, "%s: Unkown getdate() error\n"), p);
739*0Sstevel@tonic-gate 	    break;
740*0Sstevel@tonic-gate 	case 1:
741*0Sstevel@tonic-gate 	    fprintf(stderr,
742*0Sstevel@tonic-gate 		dgettext(domainname, "%s: %s null or undefined\n"), p, name);
743*0Sstevel@tonic-gate 	    break;
744*0Sstevel@tonic-gate 	case 2:
745*0Sstevel@tonic-gate 	    fprintf(stderr, dgettext(domainname,
746*0Sstevel@tonic-gate 		"%s: Cannot read template file %s\n"), p, value);
747*0Sstevel@tonic-gate 	    break;
748*0Sstevel@tonic-gate 	case 3:
749*0Sstevel@tonic-gate 	    fprintf(stderr, dgettext(domainname,
750*0Sstevel@tonic-gate 		"%s: Failed to get file status information\n"), p);
751*0Sstevel@tonic-gate 	    break;
752*0Sstevel@tonic-gate 	case 4:
753*0Sstevel@tonic-gate 	    fprintf(stderr, dgettext(domainname,
754*0Sstevel@tonic-gate 		"%s: Template file %s not a regular file\n"), p, value);
755*0Sstevel@tonic-gate 	    break;
756*0Sstevel@tonic-gate 	case 5:
757*0Sstevel@tonic-gate 	    fprintf(stderr, dgettext(domainname,
758*0Sstevel@tonic-gate 		"%s: Error reading template file %s\n"), p, value);
759*0Sstevel@tonic-gate 	    break;
760*0Sstevel@tonic-gate 	case 6:
761*0Sstevel@tonic-gate 	    fprintf(stderr, dgettext(domainname,
762*0Sstevel@tonic-gate 		"%s: %s failed\n"), p, "malloc()");
763*0Sstevel@tonic-gate 	    break;
764*0Sstevel@tonic-gate 	case 7:
765*0Sstevel@tonic-gate 	    fprintf(stderr, dgettext(domainname,
766*0Sstevel@tonic-gate 		"%s: Bad date/time format\n"), p);
767*0Sstevel@tonic-gate 	    fp = fopen(value, "r");
768*0Sstevel@tonic-gate 	    if (fp == (FILE *)0)
769*0Sstevel@tonic-gate 		break;
770*0Sstevel@tonic-gate 	    now = time((time_t *)0);
771*0Sstevel@tonic-gate 	    tm = localtime(&now);
772*0Sstevel@tonic-gate 	    fprintf(stderr, dgettext(domainname,
773*0Sstevel@tonic-gate 		"The following are examples of valid formats:\n"));
774*0Sstevel@tonic-gate 	    while (fgets(fmt, sizeof (fmt), fp)) {
775*0Sstevel@tonic-gate 		if (strchr(fmt, '%') == (char *)0)
776*0Sstevel@tonic-gate 		    continue;
777*0Sstevel@tonic-gate 		fprintf(stderr, "    ");
778*0Sstevel@tonic-gate 	        (void) strftime(line, sizeof (line), fmt, tm);
779*0Sstevel@tonic-gate 		fprintf(stderr, "%s", line);
780*0Sstevel@tonic-gate 	    }
781*0Sstevel@tonic-gate 	    (void) fclose(fp);
782*0Sstevel@tonic-gate 	    break;
783*0Sstevel@tonic-gate 	case 8:
784*0Sstevel@tonic-gate 	    (void) fprintf(stderr, dgettext(domainname,
785*0Sstevel@tonic-gate 		"%s: Invalid date specification\n"), p);
786*0Sstevel@tonic-gate 	    break;
787*0Sstevel@tonic-gate     }
788*0Sstevel@tonic-gate }
789*0Sstevel@tonic-gate 
790*0Sstevel@tonic-gate #undef yylex
791*0Sstevel@tonic-gate static int
792*0Sstevel@tonic-gate yylex()
793*0Sstevel@tonic-gate {
794*0Sstevel@tonic-gate     char	c;
795*0Sstevel@tonic-gate     char	*p;
796*0Sstevel@tonic-gate     char	buff[20];
797*0Sstevel@tonic-gate     int		Count;
798*0Sstevel@tonic-gate     int		sign;
799*0Sstevel@tonic-gate 
800*0Sstevel@tonic-gate     for ( ; ; ) {
801*0Sstevel@tonic-gate 	while (isspace((u_char)*yyInput))
802*0Sstevel@tonic-gate 	    yyInput++;
803*0Sstevel@tonic-gate 
804*0Sstevel@tonic-gate 	if (isdigit((u_char)(c = *yyInput)) || c == '-' || c == '+') {
805*0Sstevel@tonic-gate 	    if (c == '-' || c == '+') {
806*0Sstevel@tonic-gate 		sign = c == '-' ? -1 : 1;
807*0Sstevel@tonic-gate 		if (!isdigit((u_char)*++yyInput))
808*0Sstevel@tonic-gate 		    /* skip the '-' sign */
809*0Sstevel@tonic-gate 		    continue;
810*0Sstevel@tonic-gate 	    }
811*0Sstevel@tonic-gate 	    else
812*0Sstevel@tonic-gate 		sign = 0;
813*0Sstevel@tonic-gate 	    yylval.Number = 0;
814*0Sstevel@tonic-gate 	    while (isdigit((u_char)(c = *yyInput++))) {
815*0Sstevel@tonic-gate 		int n;
816*0Sstevel@tonic-gate 		char digit = c;
817*0Sstevel@tonic-gate 		(void) sscanf(&digit, "%1d", &n);
818*0Sstevel@tonic-gate 		yylval.Number = 10 * yylval.Number + n;
819*0Sstevel@tonic-gate 	    }
820*0Sstevel@tonic-gate 	    yyInput--;
821*0Sstevel@tonic-gate 	    if (sign < 0)
822*0Sstevel@tonic-gate 		yylval.Number = -yylval.Number;
823*0Sstevel@tonic-gate 	    return sign ? tSNUMBER : tUNUMBER;
824*0Sstevel@tonic-gate 	}
825*0Sstevel@tonic-gate 	if (isalpha((u_char)c)) {
826*0Sstevel@tonic-gate 	    for (p = buff; isalpha((u_char)(c = *yyInput++)) || c == '.'; )
827*0Sstevel@tonic-gate 		if (p < &buff[sizeof (buff) - 1])
828*0Sstevel@tonic-gate 		    *p++ = c;
829*0Sstevel@tonic-gate 	    *p = '\0';
830*0Sstevel@tonic-gate 	    yyInput--;
831*0Sstevel@tonic-gate 	    return LookupWord(buff);
832*0Sstevel@tonic-gate 	}
833*0Sstevel@tonic-gate 	if (c != '(')
834*0Sstevel@tonic-gate 	    return *yyInput++;
835*0Sstevel@tonic-gate 	Count = 0;
836*0Sstevel@tonic-gate 	do {
837*0Sstevel@tonic-gate 	    c = *yyInput++;
838*0Sstevel@tonic-gate 	    if (c == '\0')
839*0Sstevel@tonic-gate 		return c;
840*0Sstevel@tonic-gate 	    if (c == '(')
841*0Sstevel@tonic-gate 		Count++;
842*0Sstevel@tonic-gate 	    else if (c == ')')
843*0Sstevel@tonic-gate 		Count--;
844*0Sstevel@tonic-gate 	} while (Count > 0);
845*0Sstevel@tonic-gate     }
846*0Sstevel@tonic-gate }
847*0Sstevel@tonic-gate 
848*0Sstevel@tonic-gate 
849*0Sstevel@tonic-gate time_t
850*0Sstevel@tonic-gate getreldate(p, now)
851*0Sstevel@tonic-gate     char		*p;
852*0Sstevel@tonic-gate     struct timeb	*now;
853*0Sstevel@tonic-gate {
854*0Sstevel@tonic-gate     struct tm		*tm;
855*0Sstevel@tonic-gate     struct timeb	ftz;
856*0Sstevel@tonic-gate     time_t		Start;
857*0Sstevel@tonic-gate     time_t		tod;
858*0Sstevel@tonic-gate 
859*0Sstevel@tonic-gate     if (strcmp(setlocale(LC_TIME, NULL), "C")) {
860*0Sstevel@tonic-gate 	static char localedate[24];
861*0Sstevel@tonic-gate 	struct tm ltm;
862*0Sstevel@tonic-gate 
863*0Sstevel@tonic-gate 	tm = getdate(p);
864*0Sstevel@tonic-gate 	if (getdate_err == 1 /* NODATEMASK */) {
865*0Sstevel@tonic-gate 	    char buffy[BUFSIZ];
866*0Sstevel@tonic-gate 	    time_t current;
867*0Sstevel@tonic-gate 
868*0Sstevel@tonic-gate 	    printf(gettext("environment variable %s not set\n"), "DATEMSK");
869*0Sstevel@tonic-gate 	    do {
870*0Sstevel@tonic-gate 		time(&current);
871*0Sstevel@tonic-gate 		tm = localtime(&current);
872*0Sstevel@tonic-gate 		memcpy(&ltm, tm, sizeof(ltm));
873*0Sstevel@tonic-gate 		tm = &ltm;
874*0Sstevel@tonic-gate 
875*0Sstevel@tonic-gate 		(void) fputs(gettext("Enter date as mmddhhmm[yy]: "), stdout);
876*0Sstevel@tonic-gate 		(void) fflush(stdout);
877*0Sstevel@tonic-gate 		if (fgets(buffy, sizeof (buffy), stdin) == NULL) {
878*0Sstevel@tonic-gate 			(void) printf(gettext("Encountered EOF on stdin\n"));
879*0Sstevel@tonic-gate 			return(-1);
880*0Sstevel@tonic-gate 		}
881*0Sstevel@tonic-gate 	    } while (sscanf(buffy, "%2d%2d%2d%2d%2d",
882*0Sstevel@tonic-gate 		&(tm->tm_mon), &(tm->tm_mday), &(tm->tm_hour),
883*0Sstevel@tonic-gate 		&(tm->tm_min), &(tm->tm_year)) < 4);
884*0Sstevel@tonic-gate 
885*0Sstevel@tonic-gate 	    (tm->tm_mon)--;
886*0Sstevel@tonic-gate 	} else if (tm == NULL)
887*0Sstevel@tonic-gate 	    return(-1);
888*0Sstevel@tonic-gate 
889*0Sstevel@tonic-gate 	(void)sprintf(localedate, "%d:%2.2d %d/%d %d",
890*0Sstevel@tonic-gate 	    tm->tm_hour, tm->tm_min, tm->tm_mon + 1,
891*0Sstevel@tonic-gate 	    tm->tm_mday, CHECK_TM(tm->tm_year));
892*0Sstevel@tonic-gate 	p = localedate;
893*0Sstevel@tonic-gate     }
894*0Sstevel@tonic-gate 
895*0Sstevel@tonic-gate     yyInput = p;
896*0Sstevel@tonic-gate     if (now == NULL) {
897*0Sstevel@tonic-gate 	now = &ftz;
898*0Sstevel@tonic-gate 	(void) time(&ftz.time);
899*0Sstevel@tonic-gate 	/* Set the timezone global. */
900*0Sstevel@tonic-gate 	tzset();
901*0Sstevel@tonic-gate 	/* LINTED timezone is time_t so intermediate results aren't truncated */
902*0Sstevel@tonic-gate 	ftz.timezone = (int) timezone / 60;
903*0Sstevel@tonic-gate     }
904*0Sstevel@tonic-gate 
905*0Sstevel@tonic-gate     tm = localtime(&now->time);
906*0Sstevel@tonic-gate     yyYear = tm->tm_year;
907*0Sstevel@tonic-gate     yyMonth = tm->tm_mon + 1;
908*0Sstevel@tonic-gate     yyDay = tm->tm_mday;
909*0Sstevel@tonic-gate     yyTimezone = now->timezone;
910*0Sstevel@tonic-gate     yyDSTmode = DSTmaybe;
911*0Sstevel@tonic-gate     yyHour = tm->tm_hour;
912*0Sstevel@tonic-gate     yyMinutes = tm->tm_min;
913*0Sstevel@tonic-gate     yySeconds = tm->tm_sec;
914*0Sstevel@tonic-gate     yyMeridian = MER24;
915*0Sstevel@tonic-gate     yyRelSeconds = 0;
916*0Sstevel@tonic-gate     yyRelMonth = 0;
917*0Sstevel@tonic-gate     yyHaveDate = 0;
918*0Sstevel@tonic-gate     yyHaveDay = 0;
919*0Sstevel@tonic-gate     yyHaveRel = 0;
920*0Sstevel@tonic-gate     yyHaveTime = 0;
921*0Sstevel@tonic-gate     yyHaveZone = 0;
922*0Sstevel@tonic-gate 
923*0Sstevel@tonic-gate     if (yyparse()
924*0Sstevel@tonic-gate      || yyHaveTime > 1 || yyHaveZone > 1 || yyHaveDate > 1 || yyHaveDay > 1)
925*0Sstevel@tonic-gate 	return -1;
926*0Sstevel@tonic-gate 
927*0Sstevel@tonic-gate     if (yyHaveDate || yyHaveTime || yyHaveDay) {
928*0Sstevel@tonic-gate 	Start = Convert(yyMonth, yyDay, yyYear, yyHour, yyMinutes, yySeconds,
929*0Sstevel@tonic-gate 		    yyMeridian, yyDSTmode);
930*0Sstevel@tonic-gate 	if (Start < 0)
931*0Sstevel@tonic-gate 	    return -1;
932*0Sstevel@tonic-gate     }
933*0Sstevel@tonic-gate     else {
934*0Sstevel@tonic-gate 	Start = now->time;
935*0Sstevel@tonic-gate 	if (!yyHaveRel)
936*0Sstevel@tonic-gate 	    Start -= ((tm->tm_hour * 60L) + tm->tm_min * 60L) + tm->tm_sec;
937*0Sstevel@tonic-gate     }
938*0Sstevel@tonic-gate 
939*0Sstevel@tonic-gate     Start += yyRelSeconds;
940*0Sstevel@tonic-gate     Start += RelativeMonth(Start, yyRelMonth);
941*0Sstevel@tonic-gate 
942*0Sstevel@tonic-gate     if (yyHaveDay && !yyHaveDate) {
943*0Sstevel@tonic-gate 	tod = RelativeDate(Start, yyDayOrdinal, yyDayNumber);
944*0Sstevel@tonic-gate 	Start += tod;
945*0Sstevel@tonic-gate     }
946*0Sstevel@tonic-gate 
947*0Sstevel@tonic-gate     /* Have to do *something* with a legitimate -1 so it's distinguishable
948*0Sstevel@tonic-gate      * from the error return value.  (Alternately could set errno on error.) */
949*0Sstevel@tonic-gate     return Start == -1 ? 0 : Start;
950*0Sstevel@tonic-gate }
951*0Sstevel@tonic-gate 
952*0Sstevel@tonic-gate #if	defined(TEST)
953*0Sstevel@tonic-gate 
954*0Sstevel@tonic-gate /* ARGSUSED */
955*0Sstevel@tonic-gate main(ac, av)
956*0Sstevel@tonic-gate     int		ac;
957*0Sstevel@tonic-gate     char	*av[];
958*0Sstevel@tonic-gate {
959*0Sstevel@tonic-gate     char	buff[128];
960*0Sstevel@tonic-gate     time_t	d;
961*0Sstevel@tonic-gate 
962*0Sstevel@tonic-gate     (void) setlocale(LC_ALL, "");
963*0Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
964*0Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
965*0Sstevel@tonic-gate #endif
966*0Sstevel@tonic-gate     (void) textdomain(TEXT_DOMAIN);
967*0Sstevel@tonic-gate 
968*0Sstevel@tonic-gate     (void) printf(gettext("Enter date, or blank line to exit.\n\t> "));
969*0Sstevel@tonic-gate     (void) fflush(stdout);
970*0Sstevel@tonic-gate     while (gets(buff) && buff[0]) {
971*0Sstevel@tonic-gate 	d = getreldate(buff, (struct timeb *)NULL);
972*0Sstevel@tonic-gate 	if (d == -1)
973*0Sstevel@tonic-gate 	    (void) printf(gettext("Bad format - couldn't convert.\n"));
974*0Sstevel@tonic-gate 	else {
975*0Sstevel@tonic-gate 	    (void) cftime(buff, "%c\n", &d);
976*0Sstevel@tonic-gate 	    (void) printf("%s", buff);
977*0Sstevel@tonic-gate 	}
978*0Sstevel@tonic-gate 	(void) printf("\t> ");
979*0Sstevel@tonic-gate 	(void) fflush(stdout);
980*0Sstevel@tonic-gate     }
981*0Sstevel@tonic-gate     exit(0);
982*0Sstevel@tonic-gate     /* NOTREACHED */
983*0Sstevel@tonic-gate }
984*0Sstevel@tonic-gate #endif	/* defined(TEST) */
985