1%{
2/*
3 * CDDL HEADER START
4 *
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License, Version 1.0 only
7 * (the "License").  You may not use this file except in compliance
8 * with the License.
9 *
10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 * or http://www.opensolaris.org/os/licensing.
12 * See the License for the specific language governing permissions
13 * and limitations under the License.
14 *
15 * When distributing Covered Code, include this CDDL HEADER in each
16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
20 *
21 * CDDL HEADER END
22 */
23%}
24/*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
25/*	  All Rights Reserved  	*/
26
27
28%{
29#ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.4	*/
30%}
31%{
32
33#include "stdio.h"
34#include "ctype.h"
35#include "time.h"
36
37extern int yylex(void);
38extern void yyerror();
39extern void atabort(char *);
40int yyparse(void);
41extern	int	gmtflag;
42extern	int	mday[];
43extern	struct	tm *tp, at, rt;
44%}
45%token	TIME
46%token	NOW
47%token	NOON
48%token	MIDNIGHT
49%token	MINUTE
50%token	HOUR
51%token	DAY
52%token	WEEK
53%token	MONTH
54%token	YEAR
55%token	UNIT
56%token	SUFF
57%token	ZONE
58%token	AM
59%token	PM
60%token	ZULU
61%token	NEXT
62%token	NUMB
63%token	COLON
64%token	COMMA
65%token	PLUS
66%token	UNKNOWN
67%right	NUMB
68%%
69
70args
71	: time ampm timezone date incr {
72		if (at.tm_min >= 60 || at.tm_hour >= 24)
73			atabort("bad time");
74		if (at.tm_mon >= 12 || at.tm_mday > mday[at.tm_mon])
75			atabort("bad date");
76		if (at.tm_year >= 1900)
77			at.tm_year -= 1900;
78		if (at.tm_year < 70 || at.tm_year >= 139)
79			atabort("bad year");
80	}
81	| time ampm timezone date incr UNKNOWN {
82		yyerror();
83	}
84	;
85
86time
87	: hour {
88		at.tm_hour = $1;
89	}
90	| hour COLON number {
91		at.tm_hour = $1;
92		at.tm_min = $3;
93		$3 = $1;
94	}
95	| hour minute {
96		at.tm_hour = $1;
97		at.tm_min = $2;
98		$2 = $1;
99	}
100	| TIME {
101		switch ($1) {
102		case NOON:
103			at.tm_hour = 12;
104			break;
105		case MIDNIGHT:
106			at.tm_hour = 0;
107			break;
108		case NOW:
109			at.tm_hour = tp->tm_hour;
110			at.tm_min = tp->tm_min;
111			at.tm_sec = tp->tm_sec;
112			break;
113		}
114	}
115	;
116
117ampm
118	: /*empty*/
119	{
120	}
121	| SUFF {
122		switch ($1) {
123		case PM:
124			if (at.tm_hour < 1 || at.tm_hour > 12)
125				atabort("bad hour");
126				at.tm_hour %= 12;
127				at.tm_hour += 12;
128				break;
129		case AM:
130			if (at.tm_hour < 1 || at.tm_hour > 12)
131				atabort("bad hour");
132			at.tm_hour %= 12;
133			break;
134		}
135	}
136	;
137
138timezone
139	: /*empty*/
140	{
141	}
142	| ZONE {
143		if (at.tm_hour == 24 && at.tm_min != 0)
144			atabort("bad time");
145		at.tm_hour %= 24;
146		gmtflag = 1;
147	}
148	;
149
150date
151	: /*empty*/ {
152		at.tm_mday = tp->tm_mday;
153		at.tm_mon = tp->tm_mon;
154		at.tm_year = tp->tm_year;
155		if ((at.tm_hour < tp->tm_hour)
156			|| ((at.tm_hour==tp->tm_hour)&&(at.tm_min<tp->tm_min)))
157			rt.tm_mday++;
158	}
159	| MONTH number {
160		at.tm_mon = $1;
161		at.tm_mday = $2;
162		at.tm_year = tp->tm_year;
163		if (at.tm_mon < tp->tm_mon)
164			at.tm_year++;
165	}
166	| MONTH number COMMA number {
167		at.tm_mon = $1;
168		at.tm_mday = $2;
169		at.tm_year = $4;
170	}
171	| DAY {
172		at.tm_mon = tp->tm_mon;
173		at.tm_mday = tp->tm_mday;
174		at.tm_year = tp->tm_year;
175		if ($1 < 7) {
176			rt.tm_mday = $1 - tp->tm_wday;
177			if (rt.tm_mday < 0)
178				rt.tm_mday += 7;
179		} else if ($1 == 8)
180			rt.tm_mday += 1;
181	}
182	;
183
184incr
185	: /*empty*/
186	| NEXT UNIT	{ addincr:
187		switch ($2) {
188		case MINUTE:
189			rt.tm_min += $1;
190			break;
191		case HOUR:
192			rt.tm_hour += $1;
193			break;
194		case DAY:
195			rt.tm_mday += $1;
196			break;
197		case WEEK:
198			rt.tm_mday += $1 * 7;
199			break;
200		case MONTH:
201			rt.tm_mon += $1;
202			break;
203		case YEAR:
204			rt.tm_year += $1;
205			break;
206		}
207	}
208	| PLUS opt_number UNIT { goto addincr; }
209	;
210
211hour
212	: NUMB		{ $$ = $1; }
213	| NUMB NUMB	{ $$ = 10 * $1 + $2; }
214	;
215minute
216	: NUMB NUMB	{ $$ = 10 * $1 + $2; }
217	;
218number
219	: NUMB		{ $$ = $1; }
220	| number NUMB	{ $$ = 10 * $1 + $2; }
221	;
222opt_number
223	: /* empty */	{ $$ = 1; }
224	| number	{ $$ = $1; }
225	;
226
227%%
228