xref: /onnv-gate/usr/src/lib/libast/common/tm/tmxdate.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin /*
244887Schin  * Glenn Fowler
254887Schin  * AT&T Research
264887Schin  *
274887Schin  * Time_t conversion support
284887Schin  *
294887Schin  * relative times inspired by Steve Bellovin's netnews getdate(3)
304887Schin  */
314887Schin 
324887Schin #include <tmx.h>
334887Schin #include <ctype.h>
348462SApril.Chin@Sun.COM #include <debug.h>
354887Schin 
364887Schin #define dig1(s,n)	((n)=((*(s)++)-'0'))
374887Schin #define dig2(s,n)	((n)=((*(s)++)-'0')*10,(n)+=(*(s)++)-'0')
384887Schin #define dig3(s,n)	((n)=((*(s)++)-'0')*100,(n)+=((*(s)++)-'0')*10,(n)+=(*(s)++)-'0')
394887Schin #define dig4(s,n)	((n)=((*(s)++)-'0')*1000,(n)+=((*(s)++)-'0')*100,(n)+=((*(s)++)-'0')*10,(n)+=(*(s)++)-'0')
404887Schin 
4110898Sroland.mainz@nrubsig.org #undef	BREAK
4210898Sroland.mainz@nrubsig.org 
434887Schin #define BREAK		(1<<0)
444887Schin #define CCYYMMDDHHMMSS	(1<<1)
454887Schin #define CRON		(1<<2)
464887Schin #define DAY		(1<<3)
474887Schin #define EXACT		(1<<4)
484887Schin #define FINAL		(1<<5)
494887Schin #define HOLD		(1<<6)
504887Schin #define HOUR		(1<<7)
514887Schin #define LAST		(1<<8)
524887Schin #define MDAY		(1<<9)
534887Schin #define MINUTE		(1<<10)
544887Schin #define MONTH		(1<<11)
554887Schin #define NEXT		(1<<12)
564887Schin #define NSEC		(1<<13)
578462SApril.Chin@Sun.COM #define ORDINAL		(1<<14)
588462SApril.Chin@Sun.COM #define SECOND		(1<<15)
598462SApril.Chin@Sun.COM #define THIS		(1L<<16)
608462SApril.Chin@Sun.COM #define WDAY		(1L<<17)
6110898Sroland.mainz@nrubsig.org #define WORK		(1L<<18)
6210898Sroland.mainz@nrubsig.org #define YEAR		(1L<<19)
6310898Sroland.mainz@nrubsig.org #define ZONE		(1L<<20)
644887Schin 
6510898Sroland.mainz@nrubsig.org #define FFMT		"%s%s%s%s%s%s%s|"
6610898Sroland.mainz@nrubsig.org #define	FLAGS(f)	(f&EXACT)?"|EXACT":"",(f&LAST)?"|LAST":"",(f&THIS)?"|THIS":"",(f&NEXT)?"|NEXT":"",(f&ORDINAL)?"|ORDINAL":"",(f&FINAL)?"|FINAL":"",(f&WORK)?"|WORK":""
674887Schin /*
684887Schin  * parse cron range into set
694887Schin  * return: -1:error 0:* 1:some
704887Schin  */
714887Schin 
724887Schin static int
range(register char * s,char ** e,char * set,int lo,int hi)734887Schin range(register char* s, char** e, char* set, int lo, int hi)
744887Schin {
754887Schin 	int	n;
764887Schin 	int	m;
774887Schin 	int	i;
784887Schin 	char*	t;
794887Schin 
804887Schin 	while (isspace(*s) || *s == '_')
814887Schin 		s++;
824887Schin 	if (*s == '*')
834887Schin 	{
844887Schin 		*e = s + 1;
854887Schin 		return 0;
864887Schin 	}
874887Schin 	memset(set, 0, hi + 1);
884887Schin 	for (;;)
894887Schin 	{
904887Schin 		n = strtol(s, &t, 10);
914887Schin 		if (s == t || n < lo || n > hi)
924887Schin 			return -1;
934887Schin 		i = 1;
944887Schin 		if (*(s = t) == '-')
954887Schin 		{
964887Schin 			m = strtol(++s, &t, 10);
974887Schin 			if (s == t || m < n || m > hi)
984887Schin 				return -1;
994887Schin 			if (*(s = t) == '/')
1004887Schin 			{
1014887Schin 				i = strtol(++s, &t, 10);
1024887Schin 				if (s == t || i < 1)
1034887Schin 					return -1;
1044887Schin 				s = t;
1054887Schin 			}
1064887Schin 		}
1074887Schin 		else
1084887Schin 			m = n;
1094887Schin 		for (; n <= m; n += i)
1104887Schin 			set[n] = 1;
1114887Schin 		if (*s != ',')
1124887Schin 			break;
1134887Schin 		s++;
1144887Schin 	}
1154887Schin 	*e = s;
1164887Schin 	return 1;
1174887Schin }
1184887Schin 
1194887Schin /*
12010898Sroland.mainz@nrubsig.org  * normalize <p,q> to power of 10 u in tm
12110898Sroland.mainz@nrubsig.org  */
12210898Sroland.mainz@nrubsig.org 
12310898Sroland.mainz@nrubsig.org static void
powerize(Tm_t * tm,unsigned long p,unsigned long q,unsigned long u)12410898Sroland.mainz@nrubsig.org powerize(Tm_t* tm, unsigned long p, unsigned long q, unsigned long u)
12510898Sroland.mainz@nrubsig.org {
12610898Sroland.mainz@nrubsig.org 	Time_t	t = p;
12710898Sroland.mainz@nrubsig.org 
12810898Sroland.mainz@nrubsig.org 	while (q > u)
12910898Sroland.mainz@nrubsig.org 	{
13010898Sroland.mainz@nrubsig.org 		q /= 10;
13110898Sroland.mainz@nrubsig.org 		t /= 10;
13210898Sroland.mainz@nrubsig.org 	}
13310898Sroland.mainz@nrubsig.org 	while (q < u)
13410898Sroland.mainz@nrubsig.org 	{
13510898Sroland.mainz@nrubsig.org 		q *= 10;
13610898Sroland.mainz@nrubsig.org 		t *= 10;
13710898Sroland.mainz@nrubsig.org 	}
13810898Sroland.mainz@nrubsig.org 	tm->tm_nsec += (int)(t % TMX_RESOLUTION);
13910898Sroland.mainz@nrubsig.org 	tm->tm_sec += (int)(t / TMX_RESOLUTION);
14010898Sroland.mainz@nrubsig.org }
14110898Sroland.mainz@nrubsig.org 
14210898Sroland.mainz@nrubsig.org #define K1(c1)			(c1)
14310898Sroland.mainz@nrubsig.org #define K2(c1,c2)		(((c1)<<8)|(c2))
14410898Sroland.mainz@nrubsig.org #define K3(c1,c2,c3)		(((c1)<<16)|((c2)<<8)|(c3))
14510898Sroland.mainz@nrubsig.org #define K4(c1,c2,c3,c4)		(((c1)<<24)|((c2)<<16)|((c3)<<8)|(c4))
14610898Sroland.mainz@nrubsig.org 
14710898Sroland.mainz@nrubsig.org #define P_INIT(n)		w = n; p = q = 0; u = (char*)s + 1
14810898Sroland.mainz@nrubsig.org 
14910898Sroland.mainz@nrubsig.org /*
1504887Schin  * parse date expression in s and return Time_t value
1514887Schin  *
1524887Schin  * if non-null, e points to the first invalid sequence in s
1534887Schin  * now provides default values
1544887Schin  */
1554887Schin 
1564887Schin Time_t
tmxdate(register const char * s,char ** e,Time_t now)1574887Schin tmxdate(register const char* s, char** e, Time_t now)
1584887Schin {
1594887Schin 	register Tm_t*	tm;
1604887Schin 	register long	n;
1614887Schin 	register int	w;
1624887Schin 	unsigned long	set;
1634887Schin 	unsigned long	state;
1644887Schin 	unsigned long	flags;
1654887Schin 	Time_t		fix;
1664887Schin 	char*		t;
1674887Schin 	char*		u;
16810898Sroland.mainz@nrubsig.org 	const char*	o;
1694887Schin 	const char*	x;
1704887Schin 	char*		last;
1714887Schin 	char*		type;
1724887Schin 	int		day;
1734887Schin 	int		dir;
1744887Schin 	int		dst;
1754887Schin 	int		zone;
1764887Schin 	int		c;
1774887Schin 	int		f;
1784887Schin 	int		i;
1794887Schin 	int		j;
1804887Schin 	int		k;
1814887Schin 	int		l;
1824887Schin 	long		m;
18310898Sroland.mainz@nrubsig.org 	unsigned long	p;
18410898Sroland.mainz@nrubsig.org 	unsigned long	q;
1854887Schin 	Tm_zone_t*	zp;
18610898Sroland.mainz@nrubsig.org 	Tm_t		ts;
1874887Schin 	char		skip[UCHAR_MAX + 1];
1884887Schin 
1894887Schin 	/*
1904887Schin 	 * check DATEMSK first
1914887Schin 	 */
1924887Schin 
19310898Sroland.mainz@nrubsig.org 	debug((error(-1, "AHA tmxdate 2009-03-06")));
1944887Schin 	fix = tmxscan(s, &last, NiL, &t, now, 0);
1954887Schin 	if (t && !*last)
1964887Schin 	{
1974887Schin 		if (e)
1984887Schin 			*e = last;
1994887Schin 		return fix;
2004887Schin 	}
20110898Sroland.mainz@nrubsig.org 	o = s;
2024887Schin 
2034887Schin  reset:
2044887Schin 
2054887Schin 	/*
2064887Schin 	 * use now for defaults
2074887Schin 	 */
2084887Schin 
20910898Sroland.mainz@nrubsig.org 	tm = tmxtm(&ts, now, NiL);
21010898Sroland.mainz@nrubsig.org 	tm_info.date = tm->tm_zone;
2114887Schin 	day = -1;
21210898Sroland.mainz@nrubsig.org 	dir = 0;
2134887Schin 	dst = TM_DST;
2144887Schin 	set = state = 0;
2154887Schin 	type = 0;
2164887Schin 	zone = TM_LOCALZONE;
2174887Schin 	skip[0] = 0;
2184887Schin 	for (n = 1; n <= UCHAR_MAX; n++)
2194887Schin 		skip[n] = isspace(n) || strchr("_,;@=|!^()[]{}", n);
2204887Schin 
2214887Schin 	/*
2224887Schin 	 * get <weekday year month day hour minutes seconds ?[ds]t [ap]m>
2234887Schin 	 */
2244887Schin 
22510898Sroland.mainz@nrubsig.org  again:
2264887Schin 	for (;;)
2274887Schin 	{
2284887Schin 		state &= (state & HOLD) ? ~(HOLD) : ~(EXACT|LAST|NEXT|THIS);
2294887Schin 		if ((set|state) & (YEAR|MONTH|DAY))
2304887Schin 			skip['/'] = 1;
23110898Sroland.mainz@nrubsig.org 		message((-1, "AHA#%d state=" FFMT " set=" FFMT, __LINE__, FLAGS(state), FLAGS(set)));
2324887Schin 		for (;;)
2334887Schin 		{
2344887Schin 			if (*s == '.' || *s == '-' || *s == '+')
2354887Schin 			{
2364887Schin 				if (((set|state) & (YEAR|MONTH|HOUR|MINUTE|ZONE)) == (YEAR|MONTH|HOUR|MINUTE) && (i = tmgoff(s, &t, TM_LOCALZONE)) != TM_LOCALZONE)
2374887Schin 				{
2384887Schin 					zone = i;
2394887Schin 					state |= ZONE;
2404887Schin 					if (!*(s = t))
2414887Schin 						break;
2424887Schin 				}
2434887Schin 				else if (*s == '+')
2444887Schin 					break;
2454887Schin 			}
2464887Schin 			else if (!skip[*s])
2474887Schin 				break;
2484887Schin 			s++;
2494887Schin 		}
2504887Schin 		if (!*(last = (char*)s))
2514887Schin 			break;
2524887Schin 		if (*s == '#')
2534887Schin 		{
2544887Schin 			if (isdigit(*++s))
2554887Schin 			{
2564887Schin 				now = strtoull(s, &t, 0);
2574887Schin 			sns:
2584887Schin 				if (*(s = t) == '.')
2594887Schin 				{
2604887Schin 					fix = 0;
2614887Schin 					m = 1000000000;
2624887Schin 					while (isdigit(*++s))
2634887Schin 						fix += (*s - '0') * (m /= 10);
2644887Schin 					now = tmxsns(now, fix);
2654887Schin 				}
2664887Schin 				else if (now <= 0x7fffffff)
2674887Schin 					now = tmxsns(now, 0);
2684887Schin 				goto reset;
2694887Schin 			}
2704887Schin 			else if (*s++ == '#')
2714887Schin 			{
2724887Schin 				now = tmxtime(tm, zone);
2734887Schin 				goto reset;
2744887Schin 			}
2754887Schin 			break;
2764887Schin 		}
27710898Sroland.mainz@nrubsig.org 		if ((*s == 'P' || *s == 'p') && (!isalpha(*(s + 1)) || (*(s + 1) == 'T' || *(s + 1) == 't') && !isalpha(*(s + 2))))
27810898Sroland.mainz@nrubsig.org 		{
27910898Sroland.mainz@nrubsig.org 			Tm_t	otm;
28010898Sroland.mainz@nrubsig.org 
28110898Sroland.mainz@nrubsig.org 			/*
28210898Sroland.mainz@nrubsig.org 			 * iso duration
28310898Sroland.mainz@nrubsig.org 			 */
28410898Sroland.mainz@nrubsig.org 
28510898Sroland.mainz@nrubsig.org 			otm = *tm;
28610898Sroland.mainz@nrubsig.org 			t = (char*)s;
28710898Sroland.mainz@nrubsig.org 			m = 0;
28810898Sroland.mainz@nrubsig.org 			P_INIT('Y');
28910898Sroland.mainz@nrubsig.org 			do
29010898Sroland.mainz@nrubsig.org 			{
29110898Sroland.mainz@nrubsig.org 				c = *++s;
29210898Sroland.mainz@nrubsig.org 			duration_next:
29310898Sroland.mainz@nrubsig.org 				switch (c)
29410898Sroland.mainz@nrubsig.org 				{
29510898Sroland.mainz@nrubsig.org 				case 0:
29610898Sroland.mainz@nrubsig.org 					m++;
29710898Sroland.mainz@nrubsig.org 					if ((char*)s > u)
29810898Sroland.mainz@nrubsig.org 					{
29910898Sroland.mainz@nrubsig.org 						s--;
30010898Sroland.mainz@nrubsig.org 						c = '_';
30110898Sroland.mainz@nrubsig.org 						goto duration_next;
30210898Sroland.mainz@nrubsig.org 					}
30310898Sroland.mainz@nrubsig.org 					break;
30410898Sroland.mainz@nrubsig.org 				case 'T':
30510898Sroland.mainz@nrubsig.org 				case 't':
30610898Sroland.mainz@nrubsig.org 					m++;
30710898Sroland.mainz@nrubsig.org 					if ((char*)s > u)
30810898Sroland.mainz@nrubsig.org 					{
30910898Sroland.mainz@nrubsig.org 						s++;
31010898Sroland.mainz@nrubsig.org 						c = 'D';
31110898Sroland.mainz@nrubsig.org 						goto duration_next;
31210898Sroland.mainz@nrubsig.org 					}
31310898Sroland.mainz@nrubsig.org 					continue;
31410898Sroland.mainz@nrubsig.org 				case 'Y':
31510898Sroland.mainz@nrubsig.org 				case 'y':
31610898Sroland.mainz@nrubsig.org 					m = 0;
31710898Sroland.mainz@nrubsig.org 					if (q > 1)
31810898Sroland.mainz@nrubsig.org 						tm->tm_sec += (365L*24L*60L*60L) * p / q;
31910898Sroland.mainz@nrubsig.org 					else
32010898Sroland.mainz@nrubsig.org 						tm->tm_year += p;
32110898Sroland.mainz@nrubsig.org 					P_INIT('M');
32210898Sroland.mainz@nrubsig.org 					continue;
32310898Sroland.mainz@nrubsig.org 				case 'm':
32410898Sroland.mainz@nrubsig.org 					if (!m)
32510898Sroland.mainz@nrubsig.org 						m = 1;
32610898Sroland.mainz@nrubsig.org 					/*FALLTHROUGH*/
32710898Sroland.mainz@nrubsig.org 				case 'M':
32810898Sroland.mainz@nrubsig.org 					switch (*(s + 1))
32910898Sroland.mainz@nrubsig.org 					{
33010898Sroland.mainz@nrubsig.org 					case 'I':
33110898Sroland.mainz@nrubsig.org 					case 'i':
33210898Sroland.mainz@nrubsig.org 						s++;
33310898Sroland.mainz@nrubsig.org 						m = 1;
33410898Sroland.mainz@nrubsig.org 						w = 'S';
33510898Sroland.mainz@nrubsig.org 						break;
33610898Sroland.mainz@nrubsig.org 					case 'O':
33710898Sroland.mainz@nrubsig.org 					case 'o':
33810898Sroland.mainz@nrubsig.org 						s++;
33910898Sroland.mainz@nrubsig.org 						m = 0;
34010898Sroland.mainz@nrubsig.org 						w = 'H';
34110898Sroland.mainz@nrubsig.org 						break;
34210898Sroland.mainz@nrubsig.org 					case 'S':
34310898Sroland.mainz@nrubsig.org 					case 's':
34410898Sroland.mainz@nrubsig.org 						s++;
34510898Sroland.mainz@nrubsig.org 						m = 2;
34610898Sroland.mainz@nrubsig.org 						w = 's';
34710898Sroland.mainz@nrubsig.org 						break;
34810898Sroland.mainz@nrubsig.org 					}
34910898Sroland.mainz@nrubsig.org 					switch (m)
35010898Sroland.mainz@nrubsig.org 					{
35110898Sroland.mainz@nrubsig.org 					case 0:
35210898Sroland.mainz@nrubsig.org 						m = 1;
35310898Sroland.mainz@nrubsig.org 						if (q > 1)
35410898Sroland.mainz@nrubsig.org 							tm->tm_sec += (3042L*24L*60L*60L) * p / q / 100L;
35510898Sroland.mainz@nrubsig.org 						else
35610898Sroland.mainz@nrubsig.org 							tm->tm_mon += p;
35710898Sroland.mainz@nrubsig.org 						break;
35810898Sroland.mainz@nrubsig.org 					case 1:
35910898Sroland.mainz@nrubsig.org 						m = 2;
36010898Sroland.mainz@nrubsig.org 						if (q > 1)
36110898Sroland.mainz@nrubsig.org 							tm->tm_sec += (60L) * p / q;
36210898Sroland.mainz@nrubsig.org 						else
36310898Sroland.mainz@nrubsig.org 							tm->tm_min += p;
36410898Sroland.mainz@nrubsig.org 						break;
36510898Sroland.mainz@nrubsig.org 					default:
36610898Sroland.mainz@nrubsig.org 						if (q > 1)
36710898Sroland.mainz@nrubsig.org 							powerize(tm, p, q, 1000UL);
36810898Sroland.mainz@nrubsig.org 						else
36910898Sroland.mainz@nrubsig.org 							tm->tm_nsec += p * 1000000L;
37010898Sroland.mainz@nrubsig.org 						break;
37110898Sroland.mainz@nrubsig.org 					}
37210898Sroland.mainz@nrubsig.org 					P_INIT(w);
37310898Sroland.mainz@nrubsig.org 					continue;
37410898Sroland.mainz@nrubsig.org 				case 'W':
37510898Sroland.mainz@nrubsig.org 				case 'w':
37610898Sroland.mainz@nrubsig.org 					m = 0;
37710898Sroland.mainz@nrubsig.org 					if (q > 1)
37810898Sroland.mainz@nrubsig.org 						tm->tm_sec += (7L*24L*60L*60L) * p / q;
37910898Sroland.mainz@nrubsig.org 					else
38010898Sroland.mainz@nrubsig.org 						tm->tm_mday += 7 * p;
38110898Sroland.mainz@nrubsig.org 					P_INIT('D');
38210898Sroland.mainz@nrubsig.org 					continue;
38310898Sroland.mainz@nrubsig.org 				case 'D':
38410898Sroland.mainz@nrubsig.org 				case 'd':
38510898Sroland.mainz@nrubsig.org 					m = 0;
38610898Sroland.mainz@nrubsig.org 					if (q > 1)
38710898Sroland.mainz@nrubsig.org 						tm->tm_sec += (24L*60L*60L) * p / q;
38810898Sroland.mainz@nrubsig.org 					else
38910898Sroland.mainz@nrubsig.org 						tm->tm_mday += p;
39010898Sroland.mainz@nrubsig.org 					P_INIT('H');
39110898Sroland.mainz@nrubsig.org 					continue;
39210898Sroland.mainz@nrubsig.org 				case 'H':
39310898Sroland.mainz@nrubsig.org 				case 'h':
39410898Sroland.mainz@nrubsig.org 					m = 1;
39510898Sroland.mainz@nrubsig.org 					if (q > 1)
39610898Sroland.mainz@nrubsig.org 						tm->tm_sec += (60L*60L) * p / q;
39710898Sroland.mainz@nrubsig.org 					else
39810898Sroland.mainz@nrubsig.org 						tm->tm_hour += p;
39910898Sroland.mainz@nrubsig.org 					P_INIT('m');
40010898Sroland.mainz@nrubsig.org 					continue;
40110898Sroland.mainz@nrubsig.org 				case 'S':
40210898Sroland.mainz@nrubsig.org 				case 's':
40310898Sroland.mainz@nrubsig.org 					m = 2;
40410898Sroland.mainz@nrubsig.org 					/*FALLTHROUGH*/
40510898Sroland.mainz@nrubsig.org 				case ' ':
40610898Sroland.mainz@nrubsig.org 				case '_':
40710898Sroland.mainz@nrubsig.org 				case '\n':
40810898Sroland.mainz@nrubsig.org 				case '\r':
40910898Sroland.mainz@nrubsig.org 				case '\t':
41010898Sroland.mainz@nrubsig.org 				case '\v':
41110898Sroland.mainz@nrubsig.org 					if (q > 1)
41210898Sroland.mainz@nrubsig.org 						powerize(tm, p, q, 1000000000UL);
41310898Sroland.mainz@nrubsig.org 					else
41410898Sroland.mainz@nrubsig.org 						tm->tm_sec += p;
41510898Sroland.mainz@nrubsig.org 					P_INIT('U');
41610898Sroland.mainz@nrubsig.org 					continue;
41710898Sroland.mainz@nrubsig.org 				case 'U':
41810898Sroland.mainz@nrubsig.org 				case 'u':
41910898Sroland.mainz@nrubsig.org 					switch (*(s + 1))
42010898Sroland.mainz@nrubsig.org 					{
42110898Sroland.mainz@nrubsig.org 					case 'S':
42210898Sroland.mainz@nrubsig.org 					case 's':
42310898Sroland.mainz@nrubsig.org 						s++;
42410898Sroland.mainz@nrubsig.org 						break;
42510898Sroland.mainz@nrubsig.org 					}
42610898Sroland.mainz@nrubsig.org 					m = 0;
42710898Sroland.mainz@nrubsig.org 					if (q > 1)
42810898Sroland.mainz@nrubsig.org 						powerize(tm, p, q, 1000000UL);
42910898Sroland.mainz@nrubsig.org 					else
43010898Sroland.mainz@nrubsig.org 						tm->tm_nsec += p * 1000L;
43110898Sroland.mainz@nrubsig.org 					P_INIT('N');
43210898Sroland.mainz@nrubsig.org 					continue;
43310898Sroland.mainz@nrubsig.org 				case 'N':
43410898Sroland.mainz@nrubsig.org 				case 'n':
43510898Sroland.mainz@nrubsig.org 					switch (*(s + 1))
43610898Sroland.mainz@nrubsig.org 					{
43710898Sroland.mainz@nrubsig.org 					case 'S':
43810898Sroland.mainz@nrubsig.org 					case 's':
43910898Sroland.mainz@nrubsig.org 						s++;
44010898Sroland.mainz@nrubsig.org 						break;
44110898Sroland.mainz@nrubsig.org 					}
44210898Sroland.mainz@nrubsig.org 					m = 0;
44310898Sroland.mainz@nrubsig.org 					if (q > 1)
44410898Sroland.mainz@nrubsig.org 						powerize(tm, p, q, 1000000000UL);
44510898Sroland.mainz@nrubsig.org 					else
44610898Sroland.mainz@nrubsig.org 						tm->tm_nsec += p;
44710898Sroland.mainz@nrubsig.org 					P_INIT('Y');
44810898Sroland.mainz@nrubsig.org 					continue;
44910898Sroland.mainz@nrubsig.org 				case '.':
45010898Sroland.mainz@nrubsig.org 					if (q)
45110898Sroland.mainz@nrubsig.org 						goto exact;
45210898Sroland.mainz@nrubsig.org 					q = 1;
45310898Sroland.mainz@nrubsig.org 					continue;
45410898Sroland.mainz@nrubsig.org 				case '-':
45510898Sroland.mainz@nrubsig.org 					c = 'M';
45610898Sroland.mainz@nrubsig.org 					u = (char*)s++;
45710898Sroland.mainz@nrubsig.org 					while (*++u && *u != ':')
45810898Sroland.mainz@nrubsig.org 						if (*u == '-')
45910898Sroland.mainz@nrubsig.org 						{
46010898Sroland.mainz@nrubsig.org 							c = 'Y';
46110898Sroland.mainz@nrubsig.org 							break;
46210898Sroland.mainz@nrubsig.org 						}
46310898Sroland.mainz@nrubsig.org 					goto duration_next;
46410898Sroland.mainz@nrubsig.org 				case ':':
46510898Sroland.mainz@nrubsig.org 					c = 'm';
46610898Sroland.mainz@nrubsig.org 					u = (char*)s++;
46710898Sroland.mainz@nrubsig.org 					while (*++u)
46810898Sroland.mainz@nrubsig.org 						if (*u == ':')
46910898Sroland.mainz@nrubsig.org 						{
47010898Sroland.mainz@nrubsig.org 							c = 'H';
47110898Sroland.mainz@nrubsig.org 							break;
47210898Sroland.mainz@nrubsig.org 						}
47310898Sroland.mainz@nrubsig.org 					goto duration_next;
47410898Sroland.mainz@nrubsig.org 				case '0':
47510898Sroland.mainz@nrubsig.org 				case '1':
47610898Sroland.mainz@nrubsig.org 				case '2':
47710898Sroland.mainz@nrubsig.org 				case '3':
47810898Sroland.mainz@nrubsig.org 				case '4':
47910898Sroland.mainz@nrubsig.org 				case '5':
48010898Sroland.mainz@nrubsig.org 				case '6':
48110898Sroland.mainz@nrubsig.org 				case '7':
48210898Sroland.mainz@nrubsig.org 				case '8':
48310898Sroland.mainz@nrubsig.org 				case '9':
48410898Sroland.mainz@nrubsig.org 					q *= 10;
48510898Sroland.mainz@nrubsig.org 					p = p * 10 + (c - '0');
48610898Sroland.mainz@nrubsig.org 					continue;
48710898Sroland.mainz@nrubsig.org 				default:
48810898Sroland.mainz@nrubsig.org 				exact:
48910898Sroland.mainz@nrubsig.org 					*tm = otm;
49010898Sroland.mainz@nrubsig.org 					s = (const char*)t + 1;
49110898Sroland.mainz@nrubsig.org 					if (*t == 'p')
49210898Sroland.mainz@nrubsig.org 					{
49310898Sroland.mainz@nrubsig.org 						state |= HOLD|EXACT;
49410898Sroland.mainz@nrubsig.org 						set &= ~(EXACT|LAST|NEXT|THIS);
49510898Sroland.mainz@nrubsig.org 						set |= state & (EXACT|LAST|NEXT|THIS);
49610898Sroland.mainz@nrubsig.org 					}
49710898Sroland.mainz@nrubsig.org 					goto again;
49810898Sroland.mainz@nrubsig.org 				}
49910898Sroland.mainz@nrubsig.org 				break;
50010898Sroland.mainz@nrubsig.org 			} while (c);
50110898Sroland.mainz@nrubsig.org 			continue;
50210898Sroland.mainz@nrubsig.org 		}
5034887Schin 		f = -1;
5044887Schin 		if (*s == '+')
5054887Schin 		{
5064887Schin 			while (isspace(*++s) || *s == '_');
5074887Schin 			n = strtol(s, &t, 0);
5084887Schin 			if (w = t - s)
5094887Schin 			{
5104887Schin 				for (s = t; skip[*s]; s++);
5114887Schin 				state |= (f = n) ? NEXT : THIS;
5124887Schin 				set &= ~(EXACT|LAST|NEXT|THIS);
5134887Schin 				set |= state & (EXACT|LAST|NEXT|THIS);
5144887Schin 			}
5154887Schin 			else
5164887Schin 				s = last;
5174887Schin 		}
5184887Schin 		if (!(state & CRON))
5194887Schin 		{
5204887Schin 			/*
5214887Schin 			 * check for cron date
5224887Schin 			 *
5234887Schin 			 *	min hour day-of-month month day-of-week
5244887Schin 			 *
5254887Schin 			 * if it's cron then determine the next time
5264887Schin 			 * that satisfies the specification
5274887Schin 			 *
5284887Schin 			 * NOTE: the only spacing is ' '||'_'||';'
5294887Schin 			 */
5304887Schin 
5314887Schin 			i = 0;
5324887Schin 			n = *(t = (char*)s);
5334887Schin 			for (;;)
5344887Schin 			{
5354887Schin 				if (n == '*')
5364887Schin 					n = *++s;
5374887Schin 				else if (!isdigit(n))
5384887Schin 					break;
5394887Schin 				else
5404887Schin 					while ((n = *++s) == ',' || n == '-' || n == '/' || isdigit(n));
5414887Schin 				if (n != ' ' && n != '_' && n != ';')
5424887Schin 				{
5434887Schin 					if (!n)
5444887Schin 						i++;
5454887Schin 					break;
5464887Schin 				}
5474887Schin 				i++;
5484887Schin 				while ((n = *++s) == ' ' || n == '_');
5494887Schin 			}
5504887Schin 			if (i == 5)
5514887Schin 			{
5524887Schin 				Time_t	tt;
5534887Schin 				char	hit[60];
5548462SApril.Chin@Sun.COM 				char	mon[13];
5554887Schin 				char	day[7];
5564887Schin 
5574887Schin 				state |= CRON;
5584887Schin 				flags = 0;
5594887Schin 				tm->tm_sec = 0;
5604887Schin 				tm->tm_min++;
5614887Schin 				tmfix(tm);
5624887Schin 
5634887Schin 				/*
5644887Schin 				 * minute
5654887Schin 				 */
5664887Schin 
5674887Schin 				if ((k = range(t, &t, hit, 0, 59)) < 0)
5684887Schin 					break;
5694887Schin 				if (k && !hit[i = tm->tm_min])
5704887Schin 				{
5714887Schin 					hit[i] = 1;
5724887Schin 					do if (++i > 59)
5734887Schin 					{
5744887Schin 						i = 0;
5754887Schin 						if (++tm->tm_hour > 59)
5764887Schin 						{
5774887Schin 							tm->tm_min = i;
5784887Schin 							tmfix(tm);
5794887Schin 						}
5804887Schin 					} while (!hit[i]);
5814887Schin 					tm->tm_min = i;
5824887Schin 				}
5834887Schin 
5844887Schin 				/*
5854887Schin 				 * hour
5864887Schin 				 */
5874887Schin 
5884887Schin 				if ((k = range(t, &t, hit, 0, 23)) < 0)
5894887Schin 					break;
5904887Schin 				if (k && !hit[i = tm->tm_hour])
5914887Schin 				{
5924887Schin 					hit[i] = 1;
5934887Schin 					do if (++i > 23)
5944887Schin 					{
5954887Schin 						i = 0;
5964887Schin 						if (++tm->tm_mday > 28)
5974887Schin 						{
5984887Schin 							tm->tm_hour = i;
5994887Schin 							tmfix(tm);
6004887Schin 						}
6014887Schin 					} while (!hit[i]);
6024887Schin 					tm->tm_hour = i;
6034887Schin 				}
6044887Schin 
6054887Schin 				/*
6064887Schin 				 * day of month
6074887Schin 				 */
6084887Schin 
6094887Schin 				if ((k = range(t, &t, hit, 1, 31)) < 0)
6104887Schin 					break;
6114887Schin 				if (k)
6124887Schin 					flags |= DAY|MDAY;
6134887Schin 
6144887Schin 				/*
6154887Schin 				 * month
6164887Schin 				 */
6174887Schin 
6184887Schin 				if ((k = range(t, &t, mon, 1, 12)) < 0)
6194887Schin 					break;
6204887Schin 				if (k)
6214887Schin 					flags |= MONTH;
6224887Schin 				else
6234887Schin 					for (i = 1; i <= 12; i++)
6244887Schin 						mon[i] = 1;
6254887Schin 
6264887Schin 				/*
6274887Schin 				 * day of week
6284887Schin 				 */
6294887Schin 
6304887Schin 				if ((k = range(t, &t, day, 0, 6)) < 0)
6314887Schin 					break;
6324887Schin 				if (k)
6334887Schin 					flags |= WDAY;
6344887Schin 				s = t;
6354887Schin 				if (flags & (MONTH|MDAY|WDAY))
6364887Schin 				{
6374887Schin 					fix = tmxtime(tm, zone);
63810898Sroland.mainz@nrubsig.org 					tm = tmxtm(tm, fix, tm->tm_zone);
6394887Schin 					i = tm->tm_mon + 1;
6404887Schin 					j = tm->tm_mday;
6414887Schin 					k = tm->tm_wday;
6424887Schin 					for (;;)
6434887Schin 					{
6444887Schin 						if (!mon[i])
6454887Schin 						{
6464887Schin 							if (++i > 12)
6474887Schin 							{
6484887Schin 								i = 1;
6494887Schin 								tm->tm_year++;
6504887Schin 							}
6514887Schin 							tm->tm_mon = i - 1;
6524887Schin 							tm->tm_mday = 1;
6534887Schin 							tt = tmxtime(tm, zone);
6544887Schin 							if (tt < fix)
6554887Schin 								goto done;
65610898Sroland.mainz@nrubsig.org 							tm = tmxtm(tm, tt, tm->tm_zone);
6574887Schin 							i = tm->tm_mon + 1;
6584887Schin 							j = tm->tm_mday;
6594887Schin 							k = tm->tm_wday;
6604887Schin 							continue;
6614887Schin 						}
6624887Schin 						if (flags & (MDAY|WDAY))
6634887Schin 						{
6644887Schin 							if ((flags & (MDAY|WDAY)) == (MDAY|WDAY))
6654887Schin 							{
6664887Schin 								if (hit[j] && day[k])
6674887Schin 									break;
6684887Schin 							}
6694887Schin 							else if ((flags & MDAY) && hit[j])
6704887Schin 								break;
6714887Schin 							else if ((flags & WDAY) && day[k])
6724887Schin 								break;
6734887Schin 							if (++j > 28)
6744887Schin 							{
6754887Schin 								tm->tm_mon = i - 1;
6764887Schin 								tm->tm_mday = j;
67710898Sroland.mainz@nrubsig.org 								tm = tmxtm(tm, tmxtime(tm, zone), tm->tm_zone);
6784887Schin 								i = tm->tm_mon + 1;
6794887Schin 								j = tm->tm_mday;
6804887Schin 								k = tm->tm_wday;
6814887Schin 							}
6824887Schin 							else if ((flags & WDAY) && ++k > 6)
6834887Schin 								k = 0;
6844887Schin 						}
6854887Schin 						else if (flags & MONTH)
6864887Schin 							break;
6874887Schin 					}
6884887Schin 					tm->tm_mon = i - 1;
6894887Schin 					tm->tm_mday = j;
6904887Schin 					tm->tm_wday = k;
6914887Schin 				}
6924887Schin 				continue;
6934887Schin 			}
6944887Schin 			s = t;
6954887Schin 		}
6964887Schin 		n = -1;
6974887Schin 		if (isdigit(*s))
6984887Schin 		{
6994887Schin 			n = strtol(s, &t, 10);
7004887Schin 			if ((w = t - s) && *t == '.' && isdigit(*(t + 1)) && isdigit(*(t + 2)) && isdigit(*(t + 3)))
7014887Schin 			{
7024887Schin 				now = n;
7034887Schin 				goto sns;
7044887Schin 			}
7058462SApril.Chin@Sun.COM 			if ((*t == 'T' || *t == 't') && ((set|state) & (YEAR|MONTH|DAY)) == (YEAR|MONTH) && isdigit(*(t + 1)))
7068462SApril.Chin@Sun.COM 				t++;
7074887Schin 			u = t + (*t == '-');
7084887Schin 			if ((w == 2 || w == 4) && (*u == 'W' || *u == 'w') && isdigit(*(u + 1)))
7094887Schin 			{
7104887Schin 				if (w == 4)
7114887Schin 				{
7124887Schin 					if ((n -= 1900) < TM_WINDOW)
7134887Schin 						break;
7144887Schin 				}
7154887Schin 				else if (n < TM_WINDOW)
7164887Schin 					n += 100;
7174887Schin 				m = n;
7188462SApril.Chin@Sun.COM 				n = strtol(++u, &t, 10);
7198462SApril.Chin@Sun.COM 				if ((i = (t - u)) < 2 || i > 3)
7204887Schin 					break;
7218462SApril.Chin@Sun.COM 				if (i == 3)
7228462SApril.Chin@Sun.COM 				{
7238462SApril.Chin@Sun.COM 					k = n % 10;
7248462SApril.Chin@Sun.COM 					n /= 10;
7258462SApril.Chin@Sun.COM 				}
7268462SApril.Chin@Sun.COM 				else if (*t != '-')
7274887Schin 					k = 1;
7288462SApril.Chin@Sun.COM 				else if (*++t && dig1(t, k) < 1 || k > 7)
7294887Schin 					break;
7308462SApril.Chin@Sun.COM 				if (n < 0 || n > 53)
7318462SApril.Chin@Sun.COM 					break;
7328462SApril.Chin@Sun.COM 				if (k == 7)
7334887Schin 					k = 0;
7344887Schin 				tm->tm_year = m;
7358462SApril.Chin@Sun.COM 				tmweek(tm, 2, n, k);
7364887Schin 				set |= YEAR|MONTH|DAY;
7378462SApril.Chin@Sun.COM 				s = t;
7384887Schin 				continue;
7394887Schin 			}
7408462SApril.Chin@Sun.COM 			else if (w == 6 || w == 8 && (n / 1000000) > 12)
7414887Schin 			{
7428462SApril.Chin@Sun.COM 				t = (char*)s;
7434887Schin 				flags = 0;
7448462SApril.Chin@Sun.COM 				if (w == 8 || w == 6 && *u != 'T' && *u != 't')
7454887Schin 				{
7468462SApril.Chin@Sun.COM 					dig4(t, m);
7474887Schin 					if ((m -= 1900) < TM_WINDOW)
7484887Schin 						break;
7494887Schin 				}
7504887Schin 				else
7514887Schin 				{
7528462SApril.Chin@Sun.COM 					dig2(t, m);
7534887Schin 					if (m < TM_WINDOW)
7544887Schin 						m += 100;
7554887Schin 				}
7564887Schin 				flags |= YEAR;
7578462SApril.Chin@Sun.COM 				if (dig2(t, l) <= 0 || l > 12)
7584887Schin 					break;
7594887Schin 				flags |= MONTH;
7608462SApril.Chin@Sun.COM 				if (*t != 'T' && *t != 't' || !isdigit(*++t))
7618462SApril.Chin@Sun.COM 				{
7628462SApril.Chin@Sun.COM 					if (w == 6)
7638462SApril.Chin@Sun.COM 						goto save_yymm;
7648462SApril.Chin@Sun.COM 					if (dig2(t, k) < 1 || k > 31)
7658462SApril.Chin@Sun.COM 						break;
7668462SApril.Chin@Sun.COM 					flags |= DAY;
7678462SApril.Chin@Sun.COM 					goto save_yymmdd;
7688462SApril.Chin@Sun.COM 				}
7698462SApril.Chin@Sun.COM 				n = strtol(s = t, &t, 0);
7704887Schin 				if ((t - s) < 2)
7714887Schin 					break;
7724887Schin 				if (dig2(s, j) > 24)
7734887Schin 					break;
7744887Schin 				if ((t - s) < 2)
7754887Schin 				{
7764887Schin 					if ((t - s) == 1 || *t++ != '-')
7774887Schin 						break;
7784887Schin 					n = strtol(s = t, &t, 0);
7794887Schin 					if ((t - s) < 2)
7804887Schin 						break;
7814887Schin 				}
7824887Schin 				if (dig2(s, i) > 59)
7834887Schin 					break;
7844887Schin 				flags |= HOUR|MINUTE;
7854887Schin 				if ((t - s) == 2)
7864887Schin 				{
7874887Schin 					if (dig2(s, n) > (59 + TM_MAXLEAP))
7884887Schin 						break;
7894887Schin 					flags |= SECOND;
7904887Schin 				}
7914887Schin 				else if (t - s)
7924887Schin 					break;
7934887Schin 				else
7944887Schin 					n = 0;
7954887Schin 				p = 0;
7964887Schin 				if (*t == '.')
7974887Schin 				{
7984887Schin 					q = 1000000000;
7994887Schin 					while (isdigit(*++t))
8004887Schin 						p += (*t - '0') * (q /= 10);
8014887Schin 					set |= NSEC;
8024887Schin 				}
8034887Schin 				if (n > (59 + TM_MAXLEAP))
8044887Schin 					break;
8054887Schin 				goto save;
8064887Schin 			}
8074887Schin 			else if (f == -1 && isalpha(*t) && tmlex(t, &t, tm_info.format + TM_ORDINAL, TM_ORDINALS - TM_ORDINAL, NiL, 0) >= 0)
8084887Schin 			{
8098462SApril.Chin@Sun.COM 				message((-1, "AHA#%d n=%d", __LINE__, n));
8104887Schin  ordinal:
8118462SApril.Chin@Sun.COM 				if (n)
8128462SApril.Chin@Sun.COM 					n--;
8138462SApril.Chin@Sun.COM 				message((-1, "AHA#%d n=%d", __LINE__, n));
8148462SApril.Chin@Sun.COM 				state |= ((f = n) ? NEXT : THIS)|ORDINAL;
8154887Schin 				set &= ~(EXACT|LAST|NEXT|THIS);
8164887Schin 				set |= state & (EXACT|LAST|NEXT|THIS);
8174887Schin 				for (s = t; skip[*s]; s++);
8184887Schin 				if (isdigit(*s))
8194887Schin 				{
8208462SApril.Chin@Sun.COM 					if (n = strtol(s, &t, 10))
8218462SApril.Chin@Sun.COM 						n--;
8224887Schin 					s = t;
8234887Schin 					if (*s == '_')
8244887Schin 						s++;
8254887Schin 				}
8264887Schin 				else
8274887Schin 					n = -1;
82810898Sroland.mainz@nrubsig.org 				dir = f;
82910898Sroland.mainz@nrubsig.org 				message((-1, "AHA#%d f=%d n=%d state=" FFMT, __LINE__, f, n, FLAGS(state)));
8304887Schin 			}
8314887Schin 			else
8324887Schin 			{
8334887Schin 				if (!(state & (LAST|NEXT|THIS)) && ((i = t - s) == 4 && (*t == '.' && isdigit(*(t + 1)) && isdigit(*(t + 2)) && *(t + 3) != '.' || (!*t || isspace(*t) || *t == '_' || isalnum(*t)) && n >= 0 && (n % 100) < 60 && ((m = (n / 100)) < 20 || m < 24 && !((set|state) & (YEAR|MONTH|HOUR|MINUTE)))) || i > 4 && i <= 12))
8344887Schin 				{
8354887Schin 					/*
8364887Schin 					 * various { date(1) touch(1) } formats
8374887Schin 					 *
8384887Schin 					 *	[[cc]yy[mm]]ddhhmm[.ss[.nn...]]
8394887Schin 					 *	[cc]yyjjj
8404887Schin 					 *	hhmm[.ss[.nn...]]
8414887Schin 					 */
8424887Schin 
8434887Schin 					flags = 0;
8444887Schin 					if (state & CCYYMMDDHHMMSS)
8454887Schin 						break;
8464887Schin 					state |= CCYYMMDDHHMMSS;
8474887Schin 					p = 0;
8488462SApril.Chin@Sun.COM 					if ((i == 7 || i == 5) && (!*t || *t == 'Z' || *t == 'z'))
8494887Schin 					{
8504887Schin 						if (i == 7)
8514887Schin 						{
8524887Schin 							dig4(s, m);
8534887Schin 							if ((m -= 1900) < TM_WINDOW)
8544887Schin 								break;
8554887Schin 						}
8564887Schin 						else if (dig2(s, m) < TM_WINDOW)
8574887Schin 							m += 100;
8584887Schin 						dig3(s, k);
8594887Schin 						l = 1;
8604887Schin 						j = 0;
8614887Schin 						i = 0;
8624887Schin 						n = 0;
8634887Schin 						flags |= MONTH;
8644887Schin 					}
8654887Schin 					else if (i & 1)
8664887Schin 						break;
8674887Schin 					else
8684887Schin 					{
8694887Schin 						u = t;
8704887Schin 						if (i == 12)
8714887Schin 						{
8724887Schin 							x = s;
8734887Schin 							dig2(x, m);
8744887Schin 							if (m <= 12)
8754887Schin 							{
8764887Schin 								u -= 4;
8774887Schin 								i -= 4;
8784887Schin 								x = s + 8;
8794887Schin 								dig4(x, m);
8804887Schin 							}
8814887Schin 							else
8824887Schin 								dig4(s, m);
88310898Sroland.mainz@nrubsig.org 							if (m < 1969 || m >= 3000)
88410898Sroland.mainz@nrubsig.org 								break;
8854887Schin 							m -= 1900;
8864887Schin 						}
8874887Schin 						else if (i == 10)
8884887Schin 						{
8894887Schin 							x = s;
8904887Schin 							if (!dig2(x, m) || m > 12 || !dig2(x, m) || m > 31 || dig2(x, m) > 24 || dig2(x, m) > 60 || dig2(x, m) <= 60 && !(tm_info.flags & TM_DATESTYLE))
8914887Schin 								dig2(s, m);
8924887Schin 							else
8934887Schin 							{
8944887Schin 								u -= 2;
8954887Schin 								i -= 2;
8964887Schin 								x = s + 8;
8974887Schin 								dig2(x, m);
8984887Schin 							}
8994887Schin 							if (m < TM_WINDOW)
9004887Schin 								m += 100;
9014887Schin 						}
9024887Schin 						else
9034887Schin 							m = tm->tm_year;
9044887Schin 						if ((u - s) < 8)
9054887Schin 							l = tm->tm_mon + 1;
9064887Schin 						else if (dig2(s, l) <= 0 || l > 12)
9074887Schin 							break;
9084887Schin 						else
9094887Schin 							flags |= MONTH;
9104887Schin 						if ((u - s) < 6)
9114887Schin 							k = tm->tm_mday;
9124887Schin 						else if (dig2(s, k) < 1 || k > 31)
9134887Schin 							break;
9144887Schin 						else
9154887Schin 							flags |= DAY;
9164887Schin 						if ((u - s) < 4)
9174887Schin 							break;
9184887Schin 						if (dig2(s, j) > 24)
9194887Schin 							break;
9204887Schin 						if (dig2(s, i) > 59)
9214887Schin 							break;
9224887Schin 						flags |= HOUR|MINUTE;
9234887Schin 						if ((u - s) == 2)
9244887Schin 						{
9254887Schin 							dig2(s, n);
9264887Schin 							flags |= SECOND;
9274887Schin 						}
9284887Schin 						else if (u - s)
9294887Schin 							break;
9304887Schin 						else if (*t != '.')
9314887Schin 							n = 0;
9324887Schin 						else
9334887Schin 						{
9344887Schin 							n = strtol(t + 1, &t, 10);
9354887Schin 							flags |= SECOND;
9364887Schin 							if (*t == '.')
9374887Schin 							{
9384887Schin 								q = 1000000000;
9394887Schin 								while (isdigit(*++t))
9404887Schin 									p += (*t - '0') * (q /= 10);
9414887Schin 								set |= NSEC;
9424887Schin 							}
9434887Schin 						}
9444887Schin 						if (n > (59 + TM_MAXLEAP))
9454887Schin 							break;
9464887Schin 					}
9474887Schin 				save:
9484887Schin 					tm->tm_hour = j;
9494887Schin 					tm->tm_min = i;
9504887Schin 					tm->tm_sec = n;
9514887Schin 					tm->tm_nsec = p;
9528462SApril.Chin@Sun.COM 				save_yymmdd:
9538462SApril.Chin@Sun.COM 					tm->tm_mday = k;
9548462SApril.Chin@Sun.COM 				save_yymm:
9558462SApril.Chin@Sun.COM 					tm->tm_mon = l - 1;
9568462SApril.Chin@Sun.COM 					tm->tm_year = m;
9574887Schin 					s = t;
9584887Schin 					set |= flags;
9594887Schin 					continue;
9604887Schin 				}
9614887Schin 				for (s = t; skip[*s]; s++);
9624887Schin 				if (*s == ':' || *s == '.' && ((set|state) & (YEAR|MONTH|DAY|HOUR)) == (YEAR|MONTH|DAY))
9634887Schin 				{
9644887Schin 					c = *s;
9654887Schin 					if ((state & HOUR) || n > 24)
9664887Schin 						break;
9674887Schin 					while (isspace(*++s) || *s == '_');
9684887Schin 					if (!isdigit(*s))
9694887Schin 						break;
9704887Schin 					i = n;
9714887Schin 					n = strtol(s, &t, 10);
9724887Schin 					for (s = t; isspace(*s) || *s == '_'; s++);
9734887Schin 					if (n > 59)
9744887Schin 						break;
9754887Schin 					j = n;
9764887Schin 					m = 0;
9774887Schin 					if (*s == c)
9784887Schin 					{
9794887Schin 						while (isspace(*++s) || *s == '_');
9804887Schin 						if (!isdigit(*s))
9814887Schin 							break;
9824887Schin 						n = strtol(s, &t, 10);
9834887Schin 						s = t;
9844887Schin 						if (n > (59 + TM_MAXLEAP))
9854887Schin 							break;
9864887Schin 						set |= SECOND;
9874887Schin 						while (isspace(*s))
9884887Schin 							s++;
9894887Schin 						if (*s == '.')
9904887Schin 						{
9914887Schin 							q = 1000000000;
9924887Schin 							while (isdigit(*++s))
9934887Schin 								m += (*s - '0') * (q /= 10);
9944887Schin 							set |= NSEC;
9954887Schin 						}
9964887Schin 					}
9974887Schin 					else
9984887Schin 						n = 0;
9994887Schin 					set |= HOUR|MINUTE;
10004887Schin 					skip[':'] = 1;
10014887Schin 					k = tm->tm_hour;
10024887Schin 					tm->tm_hour = i;
10034887Schin 					l = tm->tm_min;
10044887Schin 					tm->tm_min = j;
10054887Schin 					tm->tm_sec = n;
10064887Schin 					tm->tm_nsec = m;
10074887Schin 					while (isspace(*s))
10084887Schin 						s++;
10094887Schin 					switch (tmlex(s, &t, tm_info.format, TM_NFORM, tm_info.format + TM_MERIDIAN, 2))
10104887Schin 					{
10114887Schin 					case TM_MERIDIAN:
10124887Schin 						s = t;
10134887Schin 						if (i == 12)
10144887Schin 							tm->tm_hour = i = 0;
10154887Schin 						break;
10164887Schin 					case TM_MERIDIAN+1:
10174887Schin 						if (i < 12)
10184887Schin 							tm->tm_hour = i += 12;
10194887Schin 						break;
10204887Schin 					}
10214887Schin 					if (f >= 0 || (state & (LAST|NEXT)))
10224887Schin 					{
10238462SApril.Chin@Sun.COM 						message((-1, "AHA#%d f=%d i=%d j=%d k=%d l=%d", __LINE__, f, i, j, k, l));
10244887Schin 						state &= ~HOLD;
10254887Schin 						if (f < 0)
10264887Schin 						{
10274887Schin 							if (state & LAST)
10284887Schin 								f = -1;
10294887Schin 							else if (state & NEXT)
10304887Schin 								f = 1;
10314887Schin 							else
10324887Schin 								f = 0;
10334887Schin 						}
10344887Schin 						if (f > 0)
10354887Schin 						{
10364887Schin 							if (i > k || i == k && j > l)
10374887Schin 								f--;
10384887Schin 						}
10394887Schin 						else if (i < k || i == k && j < l)
10404887Schin 							f++;
10414887Schin 						if (f > 0)
10424887Schin 						{
10434887Schin 							tm->tm_hour += f * 24;
10444887Schin 							while (tm->tm_hour >= 24)
10454887Schin 							{
10464887Schin 								tm->tm_hour -= 24;
10474887Schin 								tm->tm_mday++;
10484887Schin 							}
10494887Schin 						}
10504887Schin 						else if (f < 0)
10514887Schin 						{
10524887Schin 							tm->tm_hour += f * 24;
10534887Schin 							while (tm->tm_hour < 24)
10544887Schin 							{
10554887Schin 								tm->tm_hour += 24;
10564887Schin 								tm->tm_mday--;
10574887Schin 							}
10584887Schin 						}
10594887Schin 					}
10604887Schin 					continue;
10614887Schin 				}
10624887Schin 			}
10634887Schin 		}
10644887Schin 		for (;;)
10654887Schin 		{
10664887Schin 			if (*s == '-' || *s == '+')
10674887Schin 			{
10684887Schin 				if (((set|state) & (MONTH|DAY|HOUR|MINUTE)) == (MONTH|DAY|HOUR|MINUTE) || *s == '+' && (!isdigit(s[1]) || !isdigit(s[2]) || s[3] != ':' && (s[3] != '.' || ((set|state) & (YEAR|MONTH)) != (YEAR|MONTH))))
10694887Schin 					break;
10704887Schin 				s++;
10714887Schin 			}
10724887Schin 			else if (skip[*s])
10734887Schin 				s++;
10744887Schin 			else
10754887Schin 				break;
10764887Schin 		}
107710898Sroland.mainz@nrubsig.org 		if (isalpha(*s))
10784887Schin 		{
107910898Sroland.mainz@nrubsig.org 			if (n > 0)
10804887Schin 			{
108110898Sroland.mainz@nrubsig.org 				x = s;
108210898Sroland.mainz@nrubsig.org 				q = *s++;
108310898Sroland.mainz@nrubsig.org 				if (isalpha(*s))
108410898Sroland.mainz@nrubsig.org 				{
108510898Sroland.mainz@nrubsig.org 					q <<= 8;
108610898Sroland.mainz@nrubsig.org 					q |= *s++;
108710898Sroland.mainz@nrubsig.org 					if (isalpha(*s))
108810898Sroland.mainz@nrubsig.org 					{
108910898Sroland.mainz@nrubsig.org 						if (tmlex(s, &t, tm_info.format + TM_SUFFIXES, TM_PARTS - TM_SUFFIXES, NiL, 0) >= 0)
109010898Sroland.mainz@nrubsig.org 							s = t;
109110898Sroland.mainz@nrubsig.org 						if (isalpha(*s))
109210898Sroland.mainz@nrubsig.org 						{
109310898Sroland.mainz@nrubsig.org 							q <<= 8;
109410898Sroland.mainz@nrubsig.org 							q |= *s++;
109510898Sroland.mainz@nrubsig.org 							if (isalpha(*s))
109610898Sroland.mainz@nrubsig.org 							{
109710898Sroland.mainz@nrubsig.org 								q <<= 8;
109810898Sroland.mainz@nrubsig.org 								q |= *s++;
109910898Sroland.mainz@nrubsig.org 								if (isalpha(*s))
110010898Sroland.mainz@nrubsig.org 									q = 0;
110110898Sroland.mainz@nrubsig.org 							}
110210898Sroland.mainz@nrubsig.org 						}
110310898Sroland.mainz@nrubsig.org 					}
110410898Sroland.mainz@nrubsig.org 				}
110510898Sroland.mainz@nrubsig.org 				switch (q)
11064887Schin 				{
110710898Sroland.mainz@nrubsig.org 				case K1('y'):
110810898Sroland.mainz@nrubsig.org 				case K1('Y'):
110910898Sroland.mainz@nrubsig.org 				case K2('y','r'):
111010898Sroland.mainz@nrubsig.org 				case K2('Y','R'):
111110898Sroland.mainz@nrubsig.org 					tm->tm_year += n;
111210898Sroland.mainz@nrubsig.org 					set |= YEAR;
111310898Sroland.mainz@nrubsig.org 					continue;
111410898Sroland.mainz@nrubsig.org 				case K1('M'):
111510898Sroland.mainz@nrubsig.org 				case K2('m','o'):
111610898Sroland.mainz@nrubsig.org 				case K2('M','O'):
111710898Sroland.mainz@nrubsig.org 					tm->tm_mon += n;
111810898Sroland.mainz@nrubsig.org 					set |= MONTH;
111910898Sroland.mainz@nrubsig.org 					continue;
112010898Sroland.mainz@nrubsig.org 				case K1('w'):
112110898Sroland.mainz@nrubsig.org 				case K1('W'):
112210898Sroland.mainz@nrubsig.org 				case K2('w','k'):
112310898Sroland.mainz@nrubsig.org 				case K2('W','K'):
112410898Sroland.mainz@nrubsig.org 					tm->tm_mday += n * 7;
112510898Sroland.mainz@nrubsig.org 					set |= DAY;
112610898Sroland.mainz@nrubsig.org 					continue;
112710898Sroland.mainz@nrubsig.org 				case K1('d'):
112810898Sroland.mainz@nrubsig.org 				case K1('D'):
112910898Sroland.mainz@nrubsig.org 				case K2('d','a'):
113010898Sroland.mainz@nrubsig.org 				case K2('d','y'):
113110898Sroland.mainz@nrubsig.org 				case K2('D','A'):
113210898Sroland.mainz@nrubsig.org 				case K2('D','Y'):
113310898Sroland.mainz@nrubsig.org 					tm->tm_mday += n;
113410898Sroland.mainz@nrubsig.org 					set |= DAY;
11354887Schin 					continue;
113610898Sroland.mainz@nrubsig.org 				case K1('h'):
113710898Sroland.mainz@nrubsig.org 				case K1('H'):
113810898Sroland.mainz@nrubsig.org 				case K2('h','r'):
113910898Sroland.mainz@nrubsig.org 				case K2('H','R'):
114010898Sroland.mainz@nrubsig.org 					tm->tm_hour += n;
114110898Sroland.mainz@nrubsig.org 					set |= HOUR;
114210898Sroland.mainz@nrubsig.org 					continue;
114310898Sroland.mainz@nrubsig.org 				case K1('m'):
114410898Sroland.mainz@nrubsig.org 				case K2('m','n'):
114510898Sroland.mainz@nrubsig.org 				case K2('M','N'):
114610898Sroland.mainz@nrubsig.org 					tm->tm_min += n;
114710898Sroland.mainz@nrubsig.org 					set |= MINUTE;
114810898Sroland.mainz@nrubsig.org 					continue;
114910898Sroland.mainz@nrubsig.org 				case K1('s'):
115010898Sroland.mainz@nrubsig.org 				case K2('s','c'):
115110898Sroland.mainz@nrubsig.org 				case K1('S'):
115210898Sroland.mainz@nrubsig.org 				case K2('S','C'):
115310898Sroland.mainz@nrubsig.org 					tm->tm_sec += n;
115410898Sroland.mainz@nrubsig.org 					set |= SECOND;
115510898Sroland.mainz@nrubsig.org 					continue;
115610898Sroland.mainz@nrubsig.org 				case K2('m','s'):
115710898Sroland.mainz@nrubsig.org 				case K3('m','s','c'):
115810898Sroland.mainz@nrubsig.org 				case K4('m','s','e','c'):
115910898Sroland.mainz@nrubsig.org 				case K2('M','S'):
116010898Sroland.mainz@nrubsig.org 				case K3('M','S','C'):
116110898Sroland.mainz@nrubsig.org 				case K4('M','S','E','C'):
116210898Sroland.mainz@nrubsig.org 					tm->tm_nsec += n * 1000000L;
11634887Schin 					continue;
116410898Sroland.mainz@nrubsig.org 				case K1('u'):
116510898Sroland.mainz@nrubsig.org 				case K2('u','s'):
116610898Sroland.mainz@nrubsig.org 				case K3('u','s','c'):
116710898Sroland.mainz@nrubsig.org 				case K4('u','s','e','c'):
116810898Sroland.mainz@nrubsig.org 				case K1('U'):
116910898Sroland.mainz@nrubsig.org 				case K2('U','S'):
117010898Sroland.mainz@nrubsig.org 				case K3('U','S','C'):
117110898Sroland.mainz@nrubsig.org 				case K4('U','S','E','C'):
117210898Sroland.mainz@nrubsig.org 					tm->tm_nsec += n * 1000L;
11734887Schin 					continue;
117410898Sroland.mainz@nrubsig.org 				case K2('n','s'):
117510898Sroland.mainz@nrubsig.org 				case K3('n','s','c'):
117610898Sroland.mainz@nrubsig.org 				case K4('n','s','e','c'):
117710898Sroland.mainz@nrubsig.org 				case K2('N','S'):
117810898Sroland.mainz@nrubsig.org 				case K3('N','S','C'):
117910898Sroland.mainz@nrubsig.org 				case K4('N','S','E','C'):
118010898Sroland.mainz@nrubsig.org 					tm->tm_nsec += n;
118110898Sroland.mainz@nrubsig.org 					continue;
118210898Sroland.mainz@nrubsig.org 				}
118310898Sroland.mainz@nrubsig.org 				s = x;
118410898Sroland.mainz@nrubsig.org 			}
118510898Sroland.mainz@nrubsig.org 			if (n < 1000)
118610898Sroland.mainz@nrubsig.org 			{
118710898Sroland.mainz@nrubsig.org 				if ((j = tmlex(s, &t, tm_info.format, TM_NFORM, tm_info.format + TM_SUFFIXES, TM_PARTS - TM_SUFFIXES)) >= 0)
118810898Sroland.mainz@nrubsig.org 				{
118910898Sroland.mainz@nrubsig.org 					s = t;
119010898Sroland.mainz@nrubsig.org 					switch (tm_data.lex[j])
11914887Schin 					{
119210898Sroland.mainz@nrubsig.org 					case TM_EXACT:
119310898Sroland.mainz@nrubsig.org 						state |= HOLD|EXACT;
11944887Schin 						set &= ~(EXACT|LAST|NEXT|THIS);
11954887Schin 						set |= state & (EXACT|LAST|NEXT|THIS);
11964887Schin 						continue;
119710898Sroland.mainz@nrubsig.org 					case TM_LAST:
119810898Sroland.mainz@nrubsig.org 						state |= HOLD|LAST;
119910898Sroland.mainz@nrubsig.org 						set &= ~(EXACT|LAST|NEXT|THIS);
120010898Sroland.mainz@nrubsig.org 						set |= state & (EXACT|LAST|NEXT|THIS);
120110898Sroland.mainz@nrubsig.org 						continue;
120210898Sroland.mainz@nrubsig.org 					case TM_THIS:
120310898Sroland.mainz@nrubsig.org 						state |= HOLD|THIS;
120410898Sroland.mainz@nrubsig.org 						set &= ~(EXACT|LAST|NEXT|THIS);
120510898Sroland.mainz@nrubsig.org 						set |= state & (EXACT|LAST|NEXT|THIS);
120610898Sroland.mainz@nrubsig.org 						n = 0;
120710898Sroland.mainz@nrubsig.org 						continue;
120810898Sroland.mainz@nrubsig.org 					case TM_NEXT:
120910898Sroland.mainz@nrubsig.org 						/*
121010898Sroland.mainz@nrubsig.org 						 * disambiguate english "last ... in"
121110898Sroland.mainz@nrubsig.org 						 */
121210898Sroland.mainz@nrubsig.org 
121310898Sroland.mainz@nrubsig.org 						if (!((state|set) & LAST))
12144887Schin 						{
121510898Sroland.mainz@nrubsig.org 							state |= HOLD|NEXT;
12164887Schin 							set &= ~(EXACT|LAST|NEXT|THIS);
12174887Schin 							set |= state & (EXACT|LAST|NEXT|THIS);
121810898Sroland.mainz@nrubsig.org 							continue;
12194887Schin 						}
122010898Sroland.mainz@nrubsig.org 						/*FALLTHROUGH*/
122110898Sroland.mainz@nrubsig.org 					case TM_FINAL:
122210898Sroland.mainz@nrubsig.org 						state |= HOLD|THIS|FINAL;
122310898Sroland.mainz@nrubsig.org 						set &= ~(EXACT|LAST|NEXT|THIS);
122410898Sroland.mainz@nrubsig.org 						set |= state & (EXACT|LAST|NEXT|THIS|FINAL);
122510898Sroland.mainz@nrubsig.org 						continue;
122610898Sroland.mainz@nrubsig.org 					case TM_WORK:
122710898Sroland.mainz@nrubsig.org 						message((-1, "AHA#%d WORK", __LINE__));
122810898Sroland.mainz@nrubsig.org 						state |= WORK;
122910898Sroland.mainz@nrubsig.org 						set |= DAY;
12308462SApril.Chin@Sun.COM 						if (state & LAST)
12318462SApril.Chin@Sun.COM 						{
12328462SApril.Chin@Sun.COM 							state &= ~LAST;
12338462SApril.Chin@Sun.COM 							set &= ~LAST;
12348462SApril.Chin@Sun.COM 							state |= FINAL;
12358462SApril.Chin@Sun.COM 							set |= FINAL;
12368462SApril.Chin@Sun.COM 						}
12374887Schin 						goto clear_hour;
123810898Sroland.mainz@nrubsig.org 					case TM_ORDINAL:
123910898Sroland.mainz@nrubsig.org 						j += TM_ORDINALS - TM_ORDINAL;
124010898Sroland.mainz@nrubsig.org 						message((-1, "AHA#%d j=%d", __LINE__, j));
124110898Sroland.mainz@nrubsig.org 						/*FALLTHROUGH*/
124210898Sroland.mainz@nrubsig.org 					case TM_ORDINALS:
124310898Sroland.mainz@nrubsig.org 						n = j - TM_ORDINALS + 1;
124410898Sroland.mainz@nrubsig.org 						message((-1, "AHA#%d n=%d", __LINE__, n));
124510898Sroland.mainz@nrubsig.org 						goto ordinal;
124610898Sroland.mainz@nrubsig.org 					case TM_MERIDIAN:
124710898Sroland.mainz@nrubsig.org 						if (f >= 0)
124810898Sroland.mainz@nrubsig.org 							f++;
124910898Sroland.mainz@nrubsig.org 						else if (state & LAST)
125010898Sroland.mainz@nrubsig.org 							f = -1;
125110898Sroland.mainz@nrubsig.org 						else if (state & THIS)
125210898Sroland.mainz@nrubsig.org 							f = 1;
125310898Sroland.mainz@nrubsig.org 						else if (state & NEXT)
125410898Sroland.mainz@nrubsig.org 							f = 2;
125510898Sroland.mainz@nrubsig.org 						else
125610898Sroland.mainz@nrubsig.org 							f = 0;
125710898Sroland.mainz@nrubsig.org 						if (n > 0)
125810898Sroland.mainz@nrubsig.org 						{
125910898Sroland.mainz@nrubsig.org 							if (n > 24)
126010898Sroland.mainz@nrubsig.org 								goto done;
126110898Sroland.mainz@nrubsig.org 							tm->tm_hour = n;
126210898Sroland.mainz@nrubsig.org 						}
126310898Sroland.mainz@nrubsig.org 						for (k = tm->tm_hour; k < 0; k += 24);
126410898Sroland.mainz@nrubsig.org 						k %= 24;
126510898Sroland.mainz@nrubsig.org 						if (j == TM_MERIDIAN)
126610898Sroland.mainz@nrubsig.org 						{
126710898Sroland.mainz@nrubsig.org 							if (k == 12)
126810898Sroland.mainz@nrubsig.org 								tm->tm_hour -= 12;
126910898Sroland.mainz@nrubsig.org 						}
127010898Sroland.mainz@nrubsig.org 						else if (k < 12)
127110898Sroland.mainz@nrubsig.org 							tm->tm_hour += 12;
127210898Sroland.mainz@nrubsig.org 						if (n > 0)
127310898Sroland.mainz@nrubsig.org 							goto clear_min;
127410898Sroland.mainz@nrubsig.org 						continue;
127510898Sroland.mainz@nrubsig.org 					case TM_DAY_ABBREV:
127610898Sroland.mainz@nrubsig.org 						j += TM_DAY - TM_DAY_ABBREV;
127710898Sroland.mainz@nrubsig.org 						/*FALLTHROUGH*/
127810898Sroland.mainz@nrubsig.org 					case TM_DAY:
127910898Sroland.mainz@nrubsig.org 					case TM_PARTS:
128010898Sroland.mainz@nrubsig.org 					case TM_HOURS:
128110898Sroland.mainz@nrubsig.org 						state |= set & (EXACT|LAST|NEXT|THIS);
128210898Sroland.mainz@nrubsig.org 						if (!(state & (LAST|NEXT|THIS)))
128310898Sroland.mainz@nrubsig.org 							for (;;)
128410898Sroland.mainz@nrubsig.org 							{
128510898Sroland.mainz@nrubsig.org 								while (skip[*s])
128610898Sroland.mainz@nrubsig.org 									s++;
128710898Sroland.mainz@nrubsig.org 								if ((k = tmlex(s, &t, tm_info.format + TM_LAST, TM_NOISE - TM_LAST, NiL, 0)) >= 0)
128810898Sroland.mainz@nrubsig.org 								{
128910898Sroland.mainz@nrubsig.org 									s = t;
129010898Sroland.mainz@nrubsig.org 									if (k <= 2)
129110898Sroland.mainz@nrubsig.org 										state |= LAST;
129210898Sroland.mainz@nrubsig.org 									else if (k <= 5)
129310898Sroland.mainz@nrubsig.org 										state |= THIS;
129410898Sroland.mainz@nrubsig.org 									else if (k <= 8)
129510898Sroland.mainz@nrubsig.org 										state |= NEXT;
129610898Sroland.mainz@nrubsig.org 									else
129710898Sroland.mainz@nrubsig.org 										state |= EXACT;
129810898Sroland.mainz@nrubsig.org 								}
129910898Sroland.mainz@nrubsig.org 								else
130010898Sroland.mainz@nrubsig.org 								{
130110898Sroland.mainz@nrubsig.org 									state |= (n > 0) ? NEXT : THIS;
130210898Sroland.mainz@nrubsig.org 									break;
130310898Sroland.mainz@nrubsig.org 								}
130410898Sroland.mainz@nrubsig.org 								set &= ~(EXACT|LAST|NEXT|THIS);
130510898Sroland.mainz@nrubsig.org 								set |= state & (EXACT|LAST|NEXT|THIS);
130610898Sroland.mainz@nrubsig.org 							}
130710898Sroland.mainz@nrubsig.org 						/*FALLTHROUGH*/
130810898Sroland.mainz@nrubsig.org 					case TM_DAYS:
130910898Sroland.mainz@nrubsig.org 						message((-1, "AHA#%d n=%d j=%d f=%d state=" FFMT, __LINE__, n, j, f, FLAGS(state)));
131010898Sroland.mainz@nrubsig.org 						if (n == -1)
131110898Sroland.mainz@nrubsig.org 						{
131210898Sroland.mainz@nrubsig.org 							/*
131310898Sroland.mainz@nrubsig.org 							 * disambiguate english "second"
131410898Sroland.mainz@nrubsig.org 							 */
131510898Sroland.mainz@nrubsig.org 
131610898Sroland.mainz@nrubsig.org 							if (j == TM_PARTS && f == -1)
131710898Sroland.mainz@nrubsig.org 							{
131810898Sroland.mainz@nrubsig.org 								state &= ~(LAST|NEXT|THIS|ORDINAL); /*AHA*/
131910898Sroland.mainz@nrubsig.org 								n = 2;
132010898Sroland.mainz@nrubsig.org 								goto ordinal;
132110898Sroland.mainz@nrubsig.org 							}
132210898Sroland.mainz@nrubsig.org 							n = 1;
132310898Sroland.mainz@nrubsig.org 						}
132410898Sroland.mainz@nrubsig.org 
132510898Sroland.mainz@nrubsig.org 						/*
132610898Sroland.mainz@nrubsig.org 						 * disambiguate "last" vs. { "previous" "final" }
132710898Sroland.mainz@nrubsig.org 						 */
132810898Sroland.mainz@nrubsig.org 
132910898Sroland.mainz@nrubsig.org 						while (isspace(*s))
133010898Sroland.mainz@nrubsig.org 							s++;
133110898Sroland.mainz@nrubsig.org 						message((-1, "AHA#%d disambiguate LAST s='%s'", __LINE__, s));
133210898Sroland.mainz@nrubsig.org 						if ((k = tmlex(s, &t, tm_info.format + TM_NEXT, TM_EXACT - TM_NEXT, NiL, 0)) >= 0 || (k = tmlex(s, &t, tm_info.format + TM_PARTS + 3, 1, NiL, 0)) >= 0)
133310898Sroland.mainz@nrubsig.org 						{
133410898Sroland.mainz@nrubsig.org 							s = t;
133510898Sroland.mainz@nrubsig.org 							if (state & LAST)
133610898Sroland.mainz@nrubsig.org 							{
133710898Sroland.mainz@nrubsig.org 								state &= ~LAST;
133810898Sroland.mainz@nrubsig.org 								set &= ~LAST;
133910898Sroland.mainz@nrubsig.org 								state |= FINAL;
134010898Sroland.mainz@nrubsig.org 								set |= FINAL;
134110898Sroland.mainz@nrubsig.org 								message((-1, "AHA#%d LAST => FINAL", __LINE__));
134210898Sroland.mainz@nrubsig.org 							}
134310898Sroland.mainz@nrubsig.org 							else
134410898Sroland.mainz@nrubsig.org 								state &= ~(THIS|NEXT);
134510898Sroland.mainz@nrubsig.org 						}
134610898Sroland.mainz@nrubsig.org 						message((-1, "AHA#%d disambiguate LAST k=%d", __LINE__, k));
134710898Sroland.mainz@nrubsig.org 						if (state & LAST)
134810898Sroland.mainz@nrubsig.org 							n = -n;
134910898Sroland.mainz@nrubsig.org 						else if (!(state & NEXT))
135010898Sroland.mainz@nrubsig.org 							n--;
135110898Sroland.mainz@nrubsig.org 						m = (f > 0) ? f * n : n;
135210898Sroland.mainz@nrubsig.org 						message((-1, "AHA#%d f=%d n=%d i=%d j=%d k=%d l=%d m=%d state=" FFMT, __LINE__, f, n, i, j, k, l, m, FLAGS(state)));
135310898Sroland.mainz@nrubsig.org 						switch (j)
135410898Sroland.mainz@nrubsig.org 						{
135510898Sroland.mainz@nrubsig.org 						case TM_DAYS+0:
135610898Sroland.mainz@nrubsig.org 							tm->tm_mday--;
135710898Sroland.mainz@nrubsig.org 							set |= DAY;
135810898Sroland.mainz@nrubsig.org 							goto clear_hour;
135910898Sroland.mainz@nrubsig.org 						case TM_DAYS+1:
136010898Sroland.mainz@nrubsig.org 							set |= DAY;
136110898Sroland.mainz@nrubsig.org 							goto clear_hour;
136210898Sroland.mainz@nrubsig.org 						case TM_DAYS+2:
136310898Sroland.mainz@nrubsig.org 							tm->tm_mday++;
136410898Sroland.mainz@nrubsig.org 							set |= DAY;
136510898Sroland.mainz@nrubsig.org 							goto clear_hour;
136610898Sroland.mainz@nrubsig.org 						case TM_PARTS+0:
136710898Sroland.mainz@nrubsig.org 							set |= SECOND;
136810898Sroland.mainz@nrubsig.org 							if ((m < 0 ? -m : m) > (365L*24L*60L*60L))
136910898Sroland.mainz@nrubsig.org 							{
137010898Sroland.mainz@nrubsig.org 								now = tmxtime(tm, zone) + tmxsns(m, 0);
137110898Sroland.mainz@nrubsig.org 								goto reset;
137210898Sroland.mainz@nrubsig.org 							}
137310898Sroland.mainz@nrubsig.org 							tm->tm_sec += m;
137410898Sroland.mainz@nrubsig.org 							goto clear_nsec;
137510898Sroland.mainz@nrubsig.org 						case TM_PARTS+1:
137610898Sroland.mainz@nrubsig.org 							tm->tm_min += m;
137710898Sroland.mainz@nrubsig.org 							set |= MINUTE;
137810898Sroland.mainz@nrubsig.org 							goto clear_sec;
137910898Sroland.mainz@nrubsig.org 						case TM_PARTS+2:
138010898Sroland.mainz@nrubsig.org 							tm->tm_hour += m;
138110898Sroland.mainz@nrubsig.org 							set |= MINUTE;
138210898Sroland.mainz@nrubsig.org 							goto clear_min;
138310898Sroland.mainz@nrubsig.org 						case TM_PARTS+3:
138410898Sroland.mainz@nrubsig.org 							message((-1, "AHA#%d DAY m=%d n=%d%s", __LINE__, m, n, (state & LAST) ? " LAST" : ""));
138510898Sroland.mainz@nrubsig.org 							if ((state & (LAST|NEXT|THIS)) == LAST)
138610898Sroland.mainz@nrubsig.org 								tm->tm_mday = tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year));
138710898Sroland.mainz@nrubsig.org 							else if (state & ORDINAL)
138810898Sroland.mainz@nrubsig.org 								tm->tm_mday = m + 1;
138910898Sroland.mainz@nrubsig.org 							else
139010898Sroland.mainz@nrubsig.org 								tm->tm_mday += m;
139110898Sroland.mainz@nrubsig.org 							if (!(set & (FINAL|WORK)))
139210898Sroland.mainz@nrubsig.org 								set |= HOUR;
139310898Sroland.mainz@nrubsig.org 							goto clear_hour;
139410898Sroland.mainz@nrubsig.org 						case TM_PARTS+4:
139510898Sroland.mainz@nrubsig.org 							tm = tmxtm(tm, tmxtime(tm, zone), tm->tm_zone);
139610898Sroland.mainz@nrubsig.org 							tm->tm_mday += 7 * m - tm->tm_wday + 1;
139710898Sroland.mainz@nrubsig.org 							set |= DAY;
139810898Sroland.mainz@nrubsig.org 							goto clear_hour;
139910898Sroland.mainz@nrubsig.org 						case TM_PARTS+5:
140010898Sroland.mainz@nrubsig.org 							tm->tm_mon += m;
140110898Sroland.mainz@nrubsig.org 							set |= MONTH;
140210898Sroland.mainz@nrubsig.org 							goto clear_mday;
140310898Sroland.mainz@nrubsig.org 						case TM_PARTS+6:
140410898Sroland.mainz@nrubsig.org 							tm->tm_year += m;
140510898Sroland.mainz@nrubsig.org 							goto clear_mon;
140610898Sroland.mainz@nrubsig.org 						case TM_HOURS+0:
140710898Sroland.mainz@nrubsig.org 							tm->tm_mday += m;
140810898Sroland.mainz@nrubsig.org 							set |= DAY;
140910898Sroland.mainz@nrubsig.org 							goto clear_hour;
141010898Sroland.mainz@nrubsig.org 						case TM_HOURS+1:
141110898Sroland.mainz@nrubsig.org 							tm->tm_mday += m;
141210898Sroland.mainz@nrubsig.org 							tm->tm_hour = 6;
141310898Sroland.mainz@nrubsig.org 							set |= HOUR;
141410898Sroland.mainz@nrubsig.org 							goto clear_min;
141510898Sroland.mainz@nrubsig.org 						case TM_HOURS+2:
141610898Sroland.mainz@nrubsig.org 							tm->tm_mday += m;
141710898Sroland.mainz@nrubsig.org 							tm->tm_hour = 12;
141810898Sroland.mainz@nrubsig.org 							set |= HOUR;
141910898Sroland.mainz@nrubsig.org 							goto clear_min;
142010898Sroland.mainz@nrubsig.org 						case TM_HOURS+3:
142110898Sroland.mainz@nrubsig.org 							tm->tm_mday += m;
142210898Sroland.mainz@nrubsig.org 							tm->tm_hour = 18;
142310898Sroland.mainz@nrubsig.org 							set |= HOUR;
142410898Sroland.mainz@nrubsig.org 							goto clear_min;
142510898Sroland.mainz@nrubsig.org 						}
142610898Sroland.mainz@nrubsig.org 						if (m >= 0 && (state & ORDINAL))
142710898Sroland.mainz@nrubsig.org 							tm->tm_mday = 1;
142810898Sroland.mainz@nrubsig.org 						tm = tmxtm(tm, tmxtime(tm, zone), tm->tm_zone);
142910898Sroland.mainz@nrubsig.org 						day = j -= TM_DAY;
143010898Sroland.mainz@nrubsig.org 						if (!dir)
143110898Sroland.mainz@nrubsig.org 							dir = m;
143210898Sroland.mainz@nrubsig.org 						message((-1, "AHA#%d j=%d m=%d", __LINE__, j, m));
143310898Sroland.mainz@nrubsig.org 						j -= tm->tm_wday;
143410898Sroland.mainz@nrubsig.org 						message((-1, "AHA#%d mday=%d wday=%d day=%d dir=%d f=%d i=%d j=%d l=%d m=%d", __LINE__, tm->tm_mday, tm->tm_wday, day, dir, f, i, j, l, m));
143510898Sroland.mainz@nrubsig.org 						if (state & (LAST|NEXT|THIS))
143610898Sroland.mainz@nrubsig.org 						{
143710898Sroland.mainz@nrubsig.org 							if (state & ORDINAL)
143810898Sroland.mainz@nrubsig.org 							{
143910898Sroland.mainz@nrubsig.org 								while (isspace(*s))
144010898Sroland.mainz@nrubsig.org 									s++;
144110898Sroland.mainz@nrubsig.org 								if (isdigit(*s) || tmlex(s, &t, tm_info.format, TM_DAY_ABBREV, NiL, 0) >= 0)
144210898Sroland.mainz@nrubsig.org 								{
144310898Sroland.mainz@nrubsig.org 									state &= ~(LAST|NEXT|THIS);
144410898Sroland.mainz@nrubsig.org 									goto clear_hour;
144510898Sroland.mainz@nrubsig.org 								}
144610898Sroland.mainz@nrubsig.org 							}
144710898Sroland.mainz@nrubsig.org 							if (j < 0)
144810898Sroland.mainz@nrubsig.org 								j += 7;
144910898Sroland.mainz@nrubsig.org 						}
145010898Sroland.mainz@nrubsig.org 						else if (j > 0)
145110898Sroland.mainz@nrubsig.org 							j -= 7;
145210898Sroland.mainz@nrubsig.org 						message((-1, "AHA#%d day=%d mday=%d f=%d m=%d j=%d state=" FFMT, __LINE__, day, tm->tm_mday, f, m, j, FLAGS(state)));
14534887Schin 						set |= DAY;
145410898Sroland.mainz@nrubsig.org 						if (set & (FINAL|WORK))
145510898Sroland.mainz@nrubsig.org 							goto clear_hour;
145610898Sroland.mainz@nrubsig.org 						else if (state & (LAST|NEXT|THIS))
14578462SApril.Chin@Sun.COM 						{
145810898Sroland.mainz@nrubsig.org 							if (f >= 0)
145910898Sroland.mainz@nrubsig.org 								day = -1;
146010898Sroland.mainz@nrubsig.org 							else if (m > 0 && (state & (NEXT|YEAR|MONTH)) == NEXT && j >= 0)
146110898Sroland.mainz@nrubsig.org 								m--;
146210898Sroland.mainz@nrubsig.org 							tm->tm_mday += j + m * 7;
146310898Sroland.mainz@nrubsig.org 							set &= ~(LAST|NEXT|THIS|ORDINAL); /*AHA*/
146410898Sroland.mainz@nrubsig.org 							state &= ~(LAST|NEXT|THIS|ORDINAL); /*AHA*/
146510898Sroland.mainz@nrubsig.org 							if (!(state & EXACT))
146610898Sroland.mainz@nrubsig.org 								goto clear_hour;
146710898Sroland.mainz@nrubsig.org 						}
146810898Sroland.mainz@nrubsig.org 						continue;
146910898Sroland.mainz@nrubsig.org 					case TM_MONTH_ABBREV:
147010898Sroland.mainz@nrubsig.org 						j += TM_MONTH - TM_MONTH_ABBREV;
147110898Sroland.mainz@nrubsig.org 						/*FALLTHROUGH*/
147210898Sroland.mainz@nrubsig.org 					case TM_MONTH:
147310898Sroland.mainz@nrubsig.org 						if (state & MONTH)
147410898Sroland.mainz@nrubsig.org 							goto done;
147510898Sroland.mainz@nrubsig.org 						state |= MONTH;
147610898Sroland.mainz@nrubsig.org 						i = tm->tm_mon;
147710898Sroland.mainz@nrubsig.org 						tm->tm_mon = j - TM_MONTH;
147810898Sroland.mainz@nrubsig.org 						if (n < 0)
147910898Sroland.mainz@nrubsig.org 						{
148010898Sroland.mainz@nrubsig.org 							while (skip[*s])
14818462SApril.Chin@Sun.COM 								s++;
148210898Sroland.mainz@nrubsig.org 							if (isdigit(*s))
14838462SApril.Chin@Sun.COM 							{
148410898Sroland.mainz@nrubsig.org 								n = strtol(s, &t, 10);
148510898Sroland.mainz@nrubsig.org 								if (n <= 31 && *t != ':')
148610898Sroland.mainz@nrubsig.org 									s = t;
148710898Sroland.mainz@nrubsig.org 								else
148810898Sroland.mainz@nrubsig.org 									n = -1;
14898462SApril.Chin@Sun.COM 							}
14908462SApril.Chin@Sun.COM 						}
149110898Sroland.mainz@nrubsig.org 						if (n >= 0)
149210898Sroland.mainz@nrubsig.org 						{
149310898Sroland.mainz@nrubsig.org 							if (n > 31)
149410898Sroland.mainz@nrubsig.org 								goto done;
149510898Sroland.mainz@nrubsig.org 							state |= DAY|MDAY;
149610898Sroland.mainz@nrubsig.org 							tm->tm_mday = n;
149710898Sroland.mainz@nrubsig.org 							if (f > 0)
149810898Sroland.mainz@nrubsig.org 								tm->tm_year += f;
149910898Sroland.mainz@nrubsig.org 						}
150010898Sroland.mainz@nrubsig.org 						if (state & (LAST|NEXT|THIS))
15014887Schin 						{
150210898Sroland.mainz@nrubsig.org 							n = i;
150310898Sroland.mainz@nrubsig.org 							goto rel_month;
15044887Schin 						}
150510898Sroland.mainz@nrubsig.org 						continue;
150610898Sroland.mainz@nrubsig.org 					case TM_UT:
150710898Sroland.mainz@nrubsig.org 						if (state & ZONE)
150810898Sroland.mainz@nrubsig.org 							goto done;
150910898Sroland.mainz@nrubsig.org 						state |= ZONE;
151010898Sroland.mainz@nrubsig.org 						zone = tmgoff(s, &t, 0);
151110898Sroland.mainz@nrubsig.org 						s = t;
151210898Sroland.mainz@nrubsig.org 						continue;
151310898Sroland.mainz@nrubsig.org 					case TM_DT:
151410898Sroland.mainz@nrubsig.org 						if (!dst)
15154887Schin 							goto done;
151610898Sroland.mainz@nrubsig.org 						if (!(state & ZONE))
151710898Sroland.mainz@nrubsig.org 						{
151810898Sroland.mainz@nrubsig.org 							dst = tm->tm_zone->dst;
151910898Sroland.mainz@nrubsig.org 							zone = tm->tm_zone->west;
152010898Sroland.mainz@nrubsig.org 						}
152110898Sroland.mainz@nrubsig.org 						zone += tmgoff(s, &t, dst);
152210898Sroland.mainz@nrubsig.org 						s = t;
152310898Sroland.mainz@nrubsig.org 						dst = 0;
152410898Sroland.mainz@nrubsig.org 						state |= ZONE;
152510898Sroland.mainz@nrubsig.org 						continue;
152610898Sroland.mainz@nrubsig.org 					case TM_NOISE:
152710898Sroland.mainz@nrubsig.org 						continue;
15284887Schin 					}
152910898Sroland.mainz@nrubsig.org 				}
153010898Sroland.mainz@nrubsig.org 				if (!(state & ZONE) && (zp = tmzone(s, &t, type, &dst)))
153110898Sroland.mainz@nrubsig.org 				{
15324887Schin 					s = t;
153310898Sroland.mainz@nrubsig.org 					zone = zp->west + dst;
153410898Sroland.mainz@nrubsig.org 					tm_info.date = zp;
15354887Schin 					state |= ZONE;
153610898Sroland.mainz@nrubsig.org 					if (n < 0)
153710898Sroland.mainz@nrubsig.org 						continue;
15384887Schin 				}
153910898Sroland.mainz@nrubsig.org 				else if (!type && (zp = tmtype(s, &t)))
154010898Sroland.mainz@nrubsig.org 				{
154110898Sroland.mainz@nrubsig.org 					s = t;
154210898Sroland.mainz@nrubsig.org 					type = zp->type;
154310898Sroland.mainz@nrubsig.org 					if (n < 0)
154410898Sroland.mainz@nrubsig.org 						continue;
154510898Sroland.mainz@nrubsig.org 				}
154610898Sroland.mainz@nrubsig.org 				state |= BREAK;
15474887Schin 			}
15484887Schin 		}
15494887Schin 		else if (*s == '/')
15504887Schin 		{
155110898Sroland.mainz@nrubsig.org 			if (!(state & (YEAR|MONTH)) && n >= 1969 && n < 3000 && (i = strtol(s + 1, &t, 10)) > 0 && i <= 12)
15524887Schin 			{
15534887Schin 				state |= YEAR;
15544887Schin 				tm->tm_year = n - 1900;
15554887Schin 				s = t;
15564887Schin 				i--;
15574887Schin 			}
15584887Schin 			else
15594887Schin 			{
15604887Schin 				if ((state & MONTH) || n <= 0 || n > 31)
15614887Schin 					break;
15624887Schin 				if (isalpha(*++s))
15634887Schin 				{
15644887Schin 					if ((i = tmlex(s, &t, tm_info.format, TM_DAY_ABBREV, NiL, 0)) < 0)
15654887Schin 						break;
15664887Schin 					if (i >= TM_MONTH)
15674887Schin 						i -= TM_MONTH;
15684887Schin 					s = t;
15694887Schin 				}
15704887Schin 				else
15714887Schin 				{
15724887Schin 					i = n - 1;
15734887Schin 					n = strtol(s, &t, 10);
15744887Schin 					s = t;
15754887Schin 					if (n <= 0 || n > 31)
15764887Schin 						break;
15774887Schin 					if (*s == '/' && !isdigit(*(s + 1)))
15784887Schin 						break;
15794887Schin 				}
15804887Schin 				state |= DAY;
15814887Schin 				tm->tm_mday = n;
15824887Schin 			}
15834887Schin 			state |= MONTH;
15844887Schin 			n = tm->tm_mon;
15854887Schin 			tm->tm_mon = i;
15864887Schin 			if (*s == '/')
15874887Schin 			{
15884887Schin 				n = strtol(++s, &t, 10);
15894887Schin 				w = t - s;
15904887Schin 				s = t;
15914887Schin 				if (*s == '/' || *s == ':' || *s == '-' || *s == '_')
15924887Schin 					s++;
15934887Schin 			}
15944887Schin 			else
15954887Schin 			{
15964887Schin 				if (state & (LAST|NEXT|THIS))
15974887Schin 				{
15984887Schin 				rel_month:
15994887Schin 					if (state & LAST)
16004887Schin 						tm->tm_year -= (tm->tm_mon < n) ? 0 : 1;
16014887Schin 					else
16024887Schin 						tm->tm_year += ((state & NEXT) ? 1 : 0) + ((tm->tm_mon < n) ? 1 : 0);
16034887Schin 					if (state & MDAY)
16044887Schin 						goto clear_hour;
16058462SApril.Chin@Sun.COM 					set &= ~(LAST|NEXT|THIS); /*AHA*/
16068462SApril.Chin@Sun.COM 					state &= ~(LAST|NEXT|THIS); /*AHA*/
16074887Schin 					goto clear_mday;
16084887Schin 				}
16094887Schin 				continue;
16104887Schin 			}
16114887Schin 		}
16124887Schin 		if (n < 0 || w > 4)
16134887Schin 			break;
16144887Schin 		if (w == 4)
16154887Schin 		{
161610898Sroland.mainz@nrubsig.org 			if ((state & YEAR) || n < 1969 || n >= 3000)
16174887Schin 				break;
16184887Schin 			state |= YEAR;
16194887Schin 			tm->tm_year = n - 1900;
16204887Schin 		}
16214887Schin 		else if (w == 3)
16224887Schin 		{
16234887Schin 			if (state & (MONTH|MDAY|WDAY))
16244887Schin 				break;
16254887Schin 			state |= MONTH|DAY|MDAY;
16264887Schin 			tm->tm_mon = 0;
16274887Schin 			tm->tm_mday = n;
16284887Schin 		}
16294887Schin 		else if (w == 2 && !(state & YEAR))
16304887Schin 		{
16314887Schin 			state |= YEAR;
16324887Schin 			if (n < TM_WINDOW)
16334887Schin 				n += 100;
16344887Schin 			tm->tm_year = n;
16354887Schin 		}
16364887Schin 		else if (!(state & MONTH) && n >= 1 && n <= 12)
16374887Schin 		{
16384887Schin 			state |= MONTH;
16394887Schin 			tm->tm_mon = n - 1;
16404887Schin 		}
16414887Schin 		else if (!(state & (MDAY|WDAY)) && n >= 1 && n <= 31)
16424887Schin 		{
16434887Schin 			state |= DAY|MDAY|WDAY;
16444887Schin 			tm->tm_mday = n;
16454887Schin 		}
16464887Schin 		else
16474887Schin 			break;
16484887Schin 		if (state & BREAK)
16494887Schin 		{
16504887Schin 			last = t;
16514887Schin 			break;
16524887Schin 		}
16534887Schin 		continue;
16544887Schin 	clear_mon:
16554887Schin 		if ((set|state) & (EXACT|MONTH))
16564887Schin 			continue;
16574887Schin 		tm->tm_mon = 0;
16584887Schin 	clear_mday:
16594887Schin 		set |= MONTH;
16604887Schin 		if ((set|state) & (EXACT|DAY|HOUR))
16614887Schin 			continue;
16624887Schin 		tm->tm_mday = 1;
16634887Schin 	clear_hour:
16648462SApril.Chin@Sun.COM 		message((-1, "AHA#%d DAY", __LINE__));
16654887Schin 		set |= DAY;
16664887Schin 		if ((set|state) & (EXACT|HOUR))
16674887Schin 			continue;
16684887Schin 		tm->tm_hour = 0;
16694887Schin 	clear_min:
16704887Schin 		set |= HOUR;
16714887Schin 		if ((set|state) & (EXACT|MINUTE))
16724887Schin 			continue;
16734887Schin 		tm->tm_min = 0;
16744887Schin 	clear_sec:
16754887Schin 		set |= MINUTE;
16764887Schin 		if ((set|state) & (EXACT|SECOND))
16774887Schin 			continue;
16784887Schin 		tm->tm_sec = 0;
16794887Schin 	clear_nsec:
16804887Schin 		set |= SECOND;
16814887Schin 		if ((set|state) & (EXACT|NSEC))
16824887Schin 			continue;
16834887Schin 		tm->tm_nsec = 0;
16844887Schin 	}
16854887Schin  done:
16864887Schin 	if (day >= 0 && !(state & (MDAY|WDAY)))
16874887Schin 	{
168810898Sroland.mainz@nrubsig.org 		message((-1, "AHA#%d day=%d dir=%d state=" FFMT, __LINE__, day, dir, FLAGS(state)));
1689*12068SRoger.Faulkner@Oracle.COM 		tmfix(tm);
16908462SApril.Chin@Sun.COM 		m = dir;
16914887Schin 		if (state & MONTH)
16924887Schin 			tm->tm_mday = 1;
16934887Schin 		else if (m < 0)
16944887Schin 			m++;
169510898Sroland.mainz@nrubsig.org 		tm = tmxtm(tm, tmxtime(tm, zone), tm->tm_zone);
16964887Schin 		j = day - tm->tm_wday;
16974887Schin 		if (j < 0)
16984887Schin 			j += 7;
16994887Schin 		tm->tm_mday += j + m * 7;
17004887Schin 		if (state & FINAL)
17014887Schin 			for (n = tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year)); (tm->tm_mday + 7) <= n; tm->tm_mday += 7);
17024887Schin 	}
17034887Schin 	else if (day < 0 && (state & FINAL) && (set & DAY))
1704*12068SRoger.Faulkner@Oracle.COM 	{
1705*12068SRoger.Faulkner@Oracle.COM 		tmfix(tm);
17064887Schin 		tm->tm_mday = tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year));
1707*12068SRoger.Faulkner@Oracle.COM 	}
170810898Sroland.mainz@nrubsig.org 	if (state & WORK)
170910898Sroland.mainz@nrubsig.org 	{
171010898Sroland.mainz@nrubsig.org 		tm->tm_mday = (set & FINAL) ? (tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year))) : 1;
171110898Sroland.mainz@nrubsig.org 		tmfix(tm);
171210898Sroland.mainz@nrubsig.org 		message((-1, "AHA#%d WORK mday=%d wday=%d", __LINE__, tm->tm_mday, tm->tm_wday));
171310898Sroland.mainz@nrubsig.org 		if (tm->tm_wday == 0 && (j = 1) || tm->tm_wday == 6 && (j = 2))
171410898Sroland.mainz@nrubsig.org 		{
171510898Sroland.mainz@nrubsig.org 			if ((tm->tm_mday + j) > (tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year))))
171610898Sroland.mainz@nrubsig.org 				j -= 3;
171710898Sroland.mainz@nrubsig.org 			tm->tm_mday += j;
171810898Sroland.mainz@nrubsig.org 		}
171910898Sroland.mainz@nrubsig.org 	}
172010898Sroland.mainz@nrubsig.org 	now = tmxtime(tm, zone);
172110898Sroland.mainz@nrubsig.org 	if (tm->tm_year <= 70 && tmxsec(now) > 31536000)
172210898Sroland.mainz@nrubsig.org 	{
172310898Sroland.mainz@nrubsig.org 		now = 0;
172410898Sroland.mainz@nrubsig.org 		last = (char*)o;
172510898Sroland.mainz@nrubsig.org 	}
17264887Schin 	if (e)
17274887Schin 		*e = last;
172810898Sroland.mainz@nrubsig.org 	return now;
17294887Schin }
1730