da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
3e14f97f673e8a630f076077de35afdd43dc1587Roger A. Faulkner* Copyright (c) 1985-2010 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Time_t conversion support
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * relative times inspired by Steve Bellovin's netnews getdate(3)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define dig2(s,n) ((n)=((*(s)++)-'0')*10,(n)+=(*(s)++)-'0')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define dig3(s,n) ((n)=((*(s)++)-'0')*100,(n)+=((*(s)++)-'0')*10,(n)+=(*(s)++)-'0')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define dig4(s,n) ((n)=((*(s)++)-'0')*1000,(n)+=((*(s)++)-'0')*100,(n)+=((*(s)++)-'0')*10,(n)+=(*(s)++)-'0')
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#define FLAGS(f) (f&EXACT)?"|EXACT":"",(f&LAST)?"|LAST":"",(f&THIS)?"|THIS":"",(f&NEXT)?"|NEXT":"",(f&ORDINAL)?"|ORDINAL":"",(f&FINAL)?"|FINAL":"",(f&WORK)?"|WORK":""
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * parse cron range into set
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return: -1:error 0:* 1:some
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinrange(register char* s, char** e, char* set, int lo, int hi)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s == '*')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *e = s + 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*(s = t) == '-')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (s == t || m < n || m > hi)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*(s = t) == '/')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (s == t || i < 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (; n <= m; n += i)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s != ',')
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz * normalize <p,q> to power of 10 u in tm
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainzpowerize(Tm_t* tm, unsigned long p, unsigned long q, unsigned long u)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz while (q > u)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz while (q < u)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#define K3(c1,c2,c3) (((c1)<<16)|((c2)<<8)|(c3))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#define K4(c1,c2,c3,c4) (((c1)<<24)|((c2)<<16)|((c3)<<8)|(c4))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz#define P_INIT(n) w = n; p = q = 0; u = (char*)s + 1
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * parse date expression in s and return Time_t value
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if non-null, e points to the first invalid sequence in s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * now provides default values
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register long n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int w;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz const char* o;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin const char* x;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz unsigned long p;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz unsigned long q;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * check DATEMSK first
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (t && !*last)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * use now for defaults
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * get <weekday year month day hour minutes seconds ?[ds]t [ap]m>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state &= (state & HOLD) ? ~(HOLD) : ~(EXACT|LAST|NEXT|THIS);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz message((-1, "AHA#%d state=" FFMT " set=" FFMT, __LINE__, FLAGS(state), FLAGS(set)));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (((set|state) & (YEAR|MONTH|HOUR|MINUTE|ZONE)) == (YEAR|MONTH|HOUR|MINUTE) && (i = tmgoff(s, &t, TM_LOCALZONE)) != TM_LOCALZONE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!*(s = t))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (*s == '+')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!skip[*s])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!*(last = (char*)s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s == '#')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*(s = t) == '.')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m = 1000000000;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (isdigit(*++s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (*s++ == '#')
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if ((*s == 'P' || *s == 'p') && (!isalpha(*(s + 1)) || (*(s + 1) == 'T' || *(s + 1) == 't') && !isalpha(*(s + 2))))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz * iso duration
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz t = (char*)s;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if ((char*)s > u)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if ((char*)s > u)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz /*FALLTHROUGH*/
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz switch (*(s + 1))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz tm->tm_sec += (3042L*24L*60L*60L) * p / q / 100L;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz /*FALLTHROUGH*/
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz switch (*(s + 1))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz switch (*(s + 1))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz u = (char*)s++;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz while (*++u && *u != ':')
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (*u == '-')
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz u = (char*)s++;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz while (*++u)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (*u == ':')
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz s = (const char*)t + 1;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (*t == 'p')
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz } while (c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s == '+')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = strtol(s, &t, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (w = t - s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (s = t; skip[*s]; s++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * check for cron date
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * min hour day-of-month month day-of-week
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if it's cron then determine the next time
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * that satisfies the specification
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * NOTE: the only spacing is ' '||'_'||';'
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = *(t = (char*)s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n == '*')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!isdigit(n))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while ((n = *++s) == ',' || n == '-' || n == '/' || isdigit(n));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (i == 5)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin do if (++i > 59)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (!hit[i]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin do if (++i > 23)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (!hit[i]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * day of month
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * day of week
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (++i > 12)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (++j > 28)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz tm = tmxtm(tm, tmxtime(tm, zone), tm->tm_zone);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((w = t - s) && *t == '.' && isdigit(*(t + 1)) && isdigit(*(t + 2)) && isdigit(*(t + 3)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((*t == 'T' || *t == 't') && ((set|state) & (YEAR|MONTH|DAY)) == (YEAR|MONTH) && isdigit(*(t + 1)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin u = t + (*t == '-');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((w == 2 || w == 4) && (*u == 'W' || *u == 'w') && isdigit(*(u + 1)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (w == 4)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (n < TM_WINDOW)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin else if (*t != '-')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (n < 0 || n > 53)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin t = (char*)s;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin n = strtol(s = t, &t, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((t - s) < 2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((t - s) < 2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = strtol(s = t, &t, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((t - s) < 2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((t - s) == 2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (t - s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*t == '.')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin q = 1000000000;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (isdigit(*++t))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (f == -1 && isalpha(*t) && tmlex(t, &t, tm_info.format + TM_ORDINAL, TM_ORDINALS - TM_ORDINAL, NiL, 0) >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (s = t; skip[*s]; s++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s == '_')
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz message((-1, "AHA#%d f=%d n=%d state=" FFMT, __LINE__, f, n, FLAGS(state)));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 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))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * various { date(1) touch(1) } formats
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * [[cc]yy[mm]]ddhhmm[.ss[.nn...]]
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * [cc]yyjjj
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * hhmm[.ss[.nn...]]
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((i == 7 || i == 5) && (!*t || *t == 'Z' || *t == 'z'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (i == 7)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (i & 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (i == 12)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (m <= 12)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x = s + 8;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin m -= 1900;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (i == 10)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 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))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin x = s + 8;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((u - s) < 8)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((u - s) < 6)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((u - s) < 4)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((u - s) == 2)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (u - s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (*t != '.')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*t == '.')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin q = 1000000000;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (isdigit(*++t))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (s = t; skip[*s]; s++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s == ':' || *s == '.' && ((set|state) & (YEAR|MONTH|DAY|HOUR)) == (YEAR|MONTH|DAY))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n > 59)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s == c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (isspace(*s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s == '.')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin q = 1000000000;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (isdigit(*++s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (isspace(*s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (tmlex(s, &t, tm_info.format, TM_NFORM, tm_info.format + TM_MERIDIAN, 2))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (i == 12)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (i < 12)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin message((-1, "AHA#%d f=%d i=%d j=%d k=%d l=%d", __LINE__, f, i, j, k, l));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (f < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (f > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (i > k || i == k && j > l)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (i < k || i == k && j < l)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (f > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (f < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 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))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (skip[*s])
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (tmlex(s, &t, tm_info.format + TM_SUFFIXES, TM_PARTS - TM_SUFFIXES, NiL, 0) >= 0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (n < 1000)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if ((j = tmlex(s, &t, tm_info.format, TM_NFORM, tm_info.format + TM_SUFFIXES, TM_PARTS - TM_SUFFIXES)) >= 0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz * disambiguate english "last ... in"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz /*FALLTHROUGH*/
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz /*FALLTHROUGH*/
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (k == 12)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz else if (k < 12)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz /*FALLTHROUGH*/
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if ((k = tmlex(s, &t, tm_info.format + TM_LAST, TM_NOISE - TM_LAST, NiL, 0)) >= 0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz else if (k <= 5)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz else if (k <= 8)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz /*FALLTHROUGH*/
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz message((-1, "AHA#%d n=%d j=%d f=%d state=" FFMT, __LINE__, n, j, f, FLAGS(state)));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (n == -1)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz * disambiguate english "second"
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz * disambiguate "last" vs. { "previous" "final" }
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz message((-1, "AHA#%d disambiguate LAST s='%s'", __LINE__, s));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz 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)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz message((-1, "AHA#%d LAST => FINAL", __LINE__));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz message((-1, "AHA#%d disambiguate LAST k=%d", __LINE__, k));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz m = (f > 0) ? f * n : n;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz 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)));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz message((-1, "AHA#%d DAY m=%d n=%d%s", __LINE__, m, n, (state & LAST) ? " LAST" : ""));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz tm->tm_mday = tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz tm = tmxtm(tm, tmxtime(tm, zone), tm->tm_zone);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz tm = tmxtm(tm, tmxtime(tm, zone), tm->tm_zone);
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz message((-1, "AHA#%d j=%d m=%d", __LINE__, j, m));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz 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));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (isdigit(*s) || tmlex(s, &t, tm_info.format, TM_DAY_ABBREV, NiL, 0) >= 0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz else if (j > 0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz 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)));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz else if (m > 0 && (state & (NEXT|YEAR|MONTH)) == NEXT && j >= 0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz /*FALLTHROUGH*/
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (!(state & ZONE) && (zp = tmzone(s, &t, type, &dst)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (*s == '/')
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (!(state & (YEAR|MONTH)) && n >= 1969 && n < 3000 && (i = strtol(s + 1, &t, 10)) > 0 && i <= 12)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((i = tmlex(s, &t, tm_info.format, TM_DAY_ABBREV, NiL, 0)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin i = n - 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n <= 0 || n > 31)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s == '/')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin w = t - s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tm->tm_year += ((state & NEXT) ? 1 : 0) + ((tm->tm_mon < n) ? 1 : 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (n < 0 || w > 4)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (w == 4)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (w == 3)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz message((-1, "AHA#%d day=%d dir=%d state=" FFMT, __LINE__, day, dir, FLAGS(state)));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (m < 0)
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz tm = tmxtm(tm, tmxtime(tm, zone), tm->tm_zone);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (j < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 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);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin tm->tm_mday = tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz tm->tm_mday = (set & FINAL) ? (tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year))) : 1;
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz message((-1, "AHA#%d WORK mday=%d wday=%d", __LINE__, tm->tm_mday, tm->tm_wday));
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (tm->tm_wday == 0 && (j = 1) || tm->tm_wday == 6 && (j = 2))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if ((tm->tm_mday + j) > (tm_data.days[tm->tm_mon] + (tm->tm_mon == 1 && tmisleapyear(tm->tm_year))))
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz if (tm->tm_year <= 70 && tmxsec(now) > 31536000)