tmp->when = f_time + v2 * SECSPERDAY;
if (bodun && (day - tp->tm_yday) == -1) { tmp->when = f_time - 1 * SECSPERDAY; tmtmp.tm_mday++; tmp->bodun = 1; } else { tmp->when = f_time + v2 * SECSPERDAY; tmp->bodun = 0; }
isnow(endp, bodun)	char	*endp;	int	bodun;{	int day = 0, flags = 0, month = 0, v1, v2, i;	int monthp, dayp, varp = 0;	struct match *matches = NULL, *tmp, *tmp2;	int interval = YEARLY;	/* how frequently the event repeats. */	int vwd = 0;	/* Variable weekday */	time_t tdiff, ttmp;	struct tm tmtmp;	/*	 * CONVENTION	 *	 * Month:     1-12	 * Monthname: Jan .. Dec	 * Day:       1-31	 * Weekday:   Mon-Sun	 *	 */	/* read first field */	/* didn't recognize anything, skip it */	if (!(v1 = getfield(endp, &endp, &flags)))		return (NULL);	/* adjust bodun rate */	if (bodun && !bodun_always)		bodun = !(arc4random() % 3);			/* Easter or Easter depending days */	if (flags & F_SPECIAL)		vwd = v1;	 /*	  * 1. {Weekday,Day} XYZ ...	  *	  *    where Day is > 12	  */	else if (flags & F_ISDAY || v1 > 12) {		/* found a day; day: 13-31 or weekday: 1-7 */		day = v1;		/* {Day,Weekday} {Month,Monthname} ... */		/* if no recognizable month, assume just a day alone -- this is		 * very unlikely and can only happen after the first 12 days.		 * --find month or use current month */		if (!(month = getfield(endp, &endp, &flags))) {			month = tp->tm_mon + 1;			/* F_ISDAY is set only if a weekday was spelled out */			/* F_ISDAY must be set if 0 < day < 8 */			if ((day <= 7) && (day >= 1))				interval = WEEKLY;			else				interval = MONTHLY;		} else if ((day <= 7) && (day >= 1))			day += 10;			/* it's a weekday; make it the first one of the month */		if (month == -1) {			month = tp->tm_mon + 1;			interval = MONTHLY;		}		if ((month > 12) || (month < 1))			return (NULL);	}	/* 2. {Monthname} XYZ ... */	else if (flags & F_ISMONTH) {		month = v1;		if (month == -1) {			month = tp->tm_mon + 1;			interval = MONTHLY;		}		/* Monthname {day,weekday} */		/* if no recognizable day, assume the first day in month */		if (!(day = getfield(endp, &endp, &flags)))			day = 1;		/* If a weekday was spelled out without an ordering,		 * assume the first of that day in the month */		if ((flags & F_ISDAY) && (day >= 1) && (day <=7))			day += 10;	}	/* Hm ... */	else {		v2 = getfield(endp, &endp, &flags);		/*		 * {Day} {Monthname} ...		 * where Day <= 12		 */		if (flags & F_ISMONTH) {			day = v1;			month = v2;			if (month == -1) {				month = tp->tm_mon + 1;				interval = MONTHLY;			}		}		/* {Month} {Weekday,Day} ...  */		else {			/* F_ISDAY set, v2 > 12, or no way to tell */			month = v1;			/* if no recognizable day, assume the first */			day = v2 ? v2 : 1;			if ((flags & F_ISDAY) && (day >= 1) && (day <= 7))				day += 10;		}	}	/* convert Weekday into *next*  Day,	 * e.g.: 'Sunday' -> 22	 *       'SundayLast' -> ??	 */	if (flags & F_ISDAY) {#if DEBUG		fprintf(stderr, "\nday: %d %s month %d\n", day, endp, month);#endif		varp = 1;		/* variable weekday, SundayLast, MondayFirst ... */		if (day < 0 || day >= 10)			vwd = day;		else {			day = tp->tm_mday + (((day - 1) - tp->tm_wday + 7) % 7);			interval = WEEKLY;		}	} else	/* Check for silliness.  Note we still catch Feb 29 */		if (!(flags & F_SPECIAL) &&		    (day > (cumdays[month + 1] - cumdays[month]) || day < 1)) {			if (!((month == 2 && day == 29) ||			    (interval == MONTHLY && day <= 31)))				return (NULL);		}	if (!(flags & F_SPECIAL)) {		monthp = month;		dayp = day;		day = cumdays[month] + day;#if DEBUG		fprintf(stderr, "day2: day %d(%d) yday %d\n", dayp, day, tp->tm_yday);#endif	/* Speed up processing for the most common situation:  yearly events	 * when the interval being checked is less than a month or so (this	 * could be less than a year, but then we have to start worrying about	 * leap years).  Only one event can match, and it's easy to find.	 * Note we can't check special events, because they can wander widely.	 */		if (((v1 = offset + f_dayAfter) < 50) && (interval == YEARLY)) {			memcpy(&tmtmp, tp, sizeof(struct tm));			tmtmp.tm_mday = dayp;			tmtmp.tm_mon = monthp - 1;			if (vwd) {			/* We want the event next year if it's late now			 * this year.  The 50-day limit means we don't have to			 * worry if next year is or isn't a leap year.			 */				if (tp->tm_yday > 300 && tmtmp.tm_mon <= 1)					variable_weekday(&vwd, tmtmp.tm_mon + 1,					    tmtmp.tm_year + TM_YEAR_BASE + 1);				else					variable_weekday(&vwd, tmtmp.tm_mon + 1,					    tmtmp.tm_year + TM_YEAR_BASE);				day = cumdays[tmtmp.tm_mon + 1] + vwd;				tmtmp.tm_mday = vwd;			}			v2 = day - tp->tm_yday;			if ((v2 > v1) || (v2 < 0)) {				if ((v2 += isleap(tp->tm_year + TM_YEAR_BASE) ? 366 : 365)				    <= v1)					tmtmp.tm_year++;				else if(!bodun || (day - tp->tm_yday) != -1)					return(NULL);			}			if ((tmp = malloc(sizeof(struct match))) == NULL)				err(1, NULL);			tmp->when = f_time + v2 * SECSPERDAY;			(void)mktime(&tmtmp);			if (strftime(tmp->print_date,			    sizeof(tmp->print_date),			/*    "%a %b %d", &tm);  Skip weekdays */			    "%b %d", &tmtmp) == 0)				tmp->print_date[sizeof(tmp->print_date) - 1] = '\0';			if (bodun && (day - tp->tm_yday) == -1)				strcpy(tmp->prefix, "   : ");			else				tmp->prefix[0] = '\0';			tmp->var   = varp;			tmp->next  = NULL;			return(tmp);		}	}	else {		varp = 1;		/* Set up v1 to the event number and ... */		v1 = vwd % (NUMEV + 1) - 1;		vwd /= (NUMEV + 1);		if (v1 < 0) {			v1 += NUMEV + 1;			vwd--;		}		dayp = monthp = 1;	/* Why not */	}	/* Compare to past and coming instances of the event.  The i == 0 part	 * of the loop corresponds to this specific instance.  Note that we	 * can leave things sort of higgledy-piggledy since a mktime() happens	 * on this before anything gets printed.  Also note that even though	 * we've effectively gotten rid of f_dayBefore, we still have to check	 * the one prior event for situations like "the 31st of every month"	 * and "yearly" events which could happen twice in one year but not in	 * the next */	tmp2 = matches;	for (i = -1; i < 2; i++) {		memcpy(&tmtmp, tp, sizeof(struct tm));		tmtmp.tm_mday = dayp;		tmtmp.tm_mon = month = monthp - 1;		do {			v2 = 0;			switch (interval) {			case WEEKLY:				tmtmp.tm_mday += 7 * i;				break;			case MONTHLY:				month += i;				tmtmp.tm_mon = month;				switch(tmtmp.tm_mon) {				case -1:					tmtmp.tm_mon = month = 11;					tmtmp.tm_year--;					break;				case 12:					tmtmp.tm_mon = month = 0;					tmtmp.tm_year++;					break;				}				if (vwd) {					v1 = vwd;					variable_weekday(&v1, tmtmp.tm_mon + 1,					    tmtmp.tm_year + TM_YEAR_BASE);					tmtmp.tm_mday = v1;				} else					tmtmp.tm_mday = dayp;				break;			case YEARLY:			default:				tmtmp.tm_year += i;				if (flags & F_SPECIAL) {					tmtmp.tm_mon = 0;	/* Gee, mktime() is nice */					tmtmp.tm_mday = spev[v1].getev(tmtmp.tm_year +					    TM_YEAR_BASE) + vwd;				} else if (vwd) {					v1 = vwd;					variable_weekday(&v1, tmtmp.tm_mon + 1,					    tmtmp.tm_year + TM_YEAR_BASE);					tmtmp.tm_mday = v1;				} else {				/* Need the following to keep Feb 29 from				 * becoming Mar 1 */				tmtmp.tm_mday = dayp;				tmtmp.tm_mon = monthp - 1;				}				break;			}			/* How many days apart are we */			if ((ttmp = mktime(&tmtmp)) == -1)				warnx("time out of range: %s", endp);			else {				tdiff = difftime(ttmp, f_time)/ SECSPERDAY;				if (tdiff <= offset + f_dayAfter ||				    (bodun && tdiff == -1)) {					if (tdiff >=  0 ||					    (bodun && tdiff == -1)) {					if ((tmp = malloc(sizeof(struct match))) == NULL)						err(1, NULL);					tmp->when = ttmp;					if (strftime(tmp->print_date,					    sizeof(tmp->print_date),					/*    "%a %b %d", &tm);  Skip weekdays */					    "%b %d", &tmtmp) == 0)						tmp->print_date[sizeof(tmp->print_date) - 1] = '\0';					if (bodun && tdiff == -1)						strcpy(tmp->prefix,						    "Bodun na ytpo ot: ");					else						tmp->prefix[0] = '\0';					tmp->var   = varp;					tmp->next  = NULL;					if (tmp2)						tmp2->next = tmp;					else						matches = tmp;					tmp2 = tmp;					v2 = (i == 1) ? 1 : 0;					}				} else					i = 2; /* No point checking in the future */			}		} while (v2 != 0);	}	return (matches);}