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