home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #ifndef UNIX
- #include <stdlib.h>
- #endif
- #include <string.h>
- #include <ctype.h>
- #include "defines.h"
- #include "globals.h"
- #include "protos.h"
-
- /***************************************************************/
- /* */
- /* int DoRem(char **s) */
- /* */
- /* Process a reminder. Return 0 if reminder not emitted, */
- /* positive if emitted, or negative if in the past and */
- /* will never be emitted. */
- /* */
- /***************************************************************/
- #ifdef __STDC__
- int DoRem(char **s)
- #else
- int DoRem(s)
- char **s;
-
- #endif
- {
- int d, m, y, wd, cons, delta, back, omit, done, jul, once, repeat, skip;
- int ud, um, uy; /* Date of UNTIL */
- int uj;
- int tim, tdelta, trep;
- int d2, m2, y2;
- Token tok;
- int trigger;
- char NeedNewToken;
-
- uj = ud = um = uy = d = m = y = tim = tdelta = trep = -1;
- back = delta = repeat = cons = wd = omit = once = skip = 0;
-
-
- done = 0;
- NeedNewToken = 1;
- while (!done) {
- if (NeedNewToken) tok = ParseToken(s);
- NeedNewToken = 1;
- switch (tok.type) {
-
- case Until_t:
- NeedNewToken = 0;
- while (!done) {
- tok = ParseToken(s);
- switch (tok.type) {
- case Year_t:
- if (uy != -1) {
- Eprint("Year duplicated in UNTIL.\n");
- return 0;
- }
- uy = tok.val;
- break;
-
- case Month_t:
- if (um != -1) {
- Eprint("Month duplicated in UNTIL.\n");
- return 0;
- }
- um = tok.val;
- break;
-
- case Day_t:
- if (ud != -1) {
- Eprint("Day duplicated in UNTIL.\n");
- return 0;
- }
- ud = tok.val;
- break;
-
- default:
- done = 1; break;
- }
- }
- if (uy == -1 || um == -1 || ud == -1) {
- Eprint("Year, month and day must all be specified after UNTIL\n");
- return 0;
- }
- if (CheckDate(ud, um, uy)) {
- Eprint("Invalid date for UNTIL.\n");
- return 0;
- }
- uj = Julian(ud, um, uy);
- done = 0; break;
-
- case Omit_t:
- NeedNewToken = 0;
- while (!done) {
- tok = ParseToken(s);
- switch(tok.type) {
- case WkDay_t:
- if (omit & (1 << tok.val)) {
- Eprint("%s duplicated.\n", tok.str);
- return 0;
- }
- omit |= 1 << tok.val;
- break;
-
- default: done = 1; break;
- }
- }
- done = 0;
- break;
-
- case At_t:
- NeedNewToken = 0;
- while (!done) {
- tok = ParseToken(s);
- switch(tok.type) {
-
- case Time_t:
- if (tim != -1) {
- Eprint("Time specified twice.\n");
- return 0;
- }
- else tim = tok.val;
- break;
-
- case Repeat_t:
- if (trep != -1) {
- Eprint("Time repeat factor specified twice.\n");
- return 0;
- }
- trep = tok.val;
- if (trep <= 0) {
- Eprint("Invalid value for timerepeat factor: %d\n", repeat);
- return 0;
- }
- break;
-
- case Delta_t:
- if (tdelta != -1) {
- Eprint("Time delta specified twice.\n");
- return 0;
- }
- tdelta = ABS(tok.val);
- break;
-
- default: done = 1; break;
- }
- }
- done = 0; break;
-
- case Eol_t:
- Eprint("Missing MSG or RUN in reminder.\n");
- return 0;
-
- case Run_t:
- case Msg_t: done = 1; break;
-
- case Skip_t:
- if (skip) {
- Eprint("Can only have one of BEFORE, AFTER or SKIP.\n");
- return 0;
- }
- skip = tok.val;
- break;
-
- case Unknown_t:
- Eprint("Unknown token %s in reminder.\n", tok.str);
- return 0;
-
- case Repeat_t:
- if (repeat) {
- Eprint("Repeat factor specified twice.\n");
- return 0;
- }
- repeat = tok.val;
- if (repeat <= 0) {
- Eprint("Invalid value for repeat factor: %d\n", repeat);
- return 0;
- }
- break;
-
- case WkDay_t:
- if (wd & (1 << tok.val)) {
- Eprint("%s duplicated.\n", tok.str);
- return 0;
- }
- wd |= 1 << tok.val;
- cons |= WKDAY_M;
- break;
-
- case Year_t:
- if (y != -1) {
- Eprint("Year specified twice.\n");
- return 0;
- }
- y = tok.val;
- cons |= YEAR_M;
- break;
-
- case Month_t:
- if (m != -1) {
- Eprint("Month specified twice.\n");
- return 0;
- }
- m = tok.val;
- cons |= MONTH_M;
- break;
-
- case Day_t:
- if (d != -1) {
- Eprint("Day specified twice.\n");
- return 0;
- }
- d = tok.val;
- cons |= DAY_M;
- break;
-
- case Delta_t:
- if (delta) {
- Eprint("Delta specified twice.\n");
- return 0;
- }
- delta = tok.val;
- break;
-
- case Back_t:
- if (back) {
- Eprint("Back specified twice.\n");
- return 0;
- }
- back = tok.val;
- break;
-
- case Once_t:
- if (once) {
- Eprint("ONCE specified twice. (How's that for an error message??)\n");
- return 0;
- }
- once = 1;
- break;
-
- default:
- Eprint("Can't use token %s here.\n", tok.str);
- return 0;
- }
- }
-
- /* Do some sanity checking on the reminder */
- if (repeat && (d == -1 || m == -1 || y == -1)) {
- Eprint("Can't use repeat counter unless you fully specify the date.\n");
- return 0;
- }
-
- if (skip && (wd & omit)) {
- Eprint("Conflict between weekday list and local OMIT\n");
- return 0;
- }
-
- if (d != -1 && m != -1 && CheckDate(d, m, y)) {
- Eprint("Illegal date specification.\n");
- return 0;
- }
- if (y != -1 && (y < BASE || y > BASE + 85)) {
- Eprint("Illegal date specification.\n");
- return 0;
- }
-
- /* Print some helpful stuff if debugging */
- if (Debug) {
- if (back > 7) Eprint("Warning: 'back' > 7 could slow execution severely.\n");
- if (delta > 30 && (omit || NumFullOmit || NumPartOmit))
- Eprint("Warning: 'delta' > 30 with OMITs could slow execution severely.\n");
- }
-
- if (omit == 127) {
- Eprint("Can't omit every day!\n");
- return 0;
- }
-
- if (IgOnce) once = 0;
-
- /* Check if we can quickly determine reminder is not to be emitted */
- if (once && !Debug && !Purge && (LastRun == JulianToday)) return 0;
-
- /* Have we passed the UNTIL date ? */
- if (uj != -1 && uj < JulianToday) {
- if (Debug) Eprint("Reminder has expired.\n");
- return -1;
- }
-
- jul = GetTriggerDate(d, m, y, wd, cons, back, repeat, omit, skip);
- if (uj != -1 && uj < jul) {
- if (Debug) Eprint("Reminder has expired.\n");
- return -1;
- }
-
- if (Calendar) {
- if (jul == JulianToday) {
- while (isspace(**s)) (*s)++;
- strcpy(WorkBuf, *s);
- CalTime = tim;
- if (tok.type == Run_t) return 2; else return 1;
- } else return 0;
- }
-
- if (jul == -1) {
- if (Debug) Eprint("Reminder has expired.\n");
- return -1;
- } else if (jul == -2) return 0;
-
- FromJulian(jul, &d2, &m2, &y2);
-
- /* If we're in "Next" mode, output this one in simple-calendar format */
- if (Next) {
- DoSubst(*s, WorkBuf, d2, m2, y2, jul, tok.type, tim, 1);
- if (!*WorkBuf) return 0;
- printf("%04d/%02d/%02d: ", y2, m2+1, d2);
- printf("%s\n", WorkBuf);
- return 0;
- }
-
- /* Figure out if the reminder should be triggered */
-
- trigger = MoveBack(jul, delta, omit);
-
- if(Debug) {
- Eprint("%sTrigger date: %s, %d %s, %d.\n",
- (trigger <= JulianToday ? "*" : ""), DayName[jul % 7],
- d2, MonthName[m2], y2);
- return 0;
- }
- if (Purge || (once && (LastRun == JulianToday))) return 0;
-
- while (isspace(**s)) (*s)++;
-
- if (trigger <= JulianToday && !(tok.type == Run_t && IgRun)) {
- /* Trigger a reminder */
- #ifdef UNIX
- if (QueueAts && (jul == JulianToday) && (tim != -1)) {
- DoAt(tim, tdelta, trep, *s, tok.type);
- }
- if (!PrintAts && (jul == JulianToday) && tim != -1) return 0;
- #endif
- if (tok.type == Msg_t) {
- if (NumEmitted == 0) {
- NumEmitted++;
- DoSubst(Banner, WorkBuf, CurDay, CurMon, CurYear,
- JulianToday, Msg_t, (int) (SystemTime()/ 60), 0);
- printf("%s\n", WorkBuf);
- }
- DoSubst(*s, WorkBuf, d2, m2, y2, jul, tok.type, tim, 0);
- printf("%s\n", WorkBuf);
- }
- else if (tok.type == Run_t) {
- DoSubst(*s, WorkBuf, d2, m2, y2, jul, tok.type, tim, 0);
- system(WorkBuf);
- }
- else Eprint("Error: Invalid token type %d\n", tok.type);
- return 1;
- } else return 0;
-
- }
-
- /***************************************************************/
- /* */
- /* GetTriggerDate */
- /* */
- /* Gets the trigger date for a reminder, returns the julian */
- /* date, or -1 if the reminder has expired. */
- /* Returns -2 if an error occurs. */
- /* */
- /***************************************************************/
- #ifdef __STDC__
- int GetTriggerDate(int d, int m, int y, int wd, int cons, int back, int repeat, int omit, int skip)
- #else
- int GetTriggerDate(d, m, y, wd, cons, back, repeat, omit, skip)
- int d, m, y, wd, cons, back, repeat, omit, skip;
- #endif
- #define MAXATTEMPTS 25 /* Maximum number of attempts before giving up */
-
- {
- int i, d2, m2, y2, jul;
- int d1, m1, y1, julstart;
- int nattempts = 0;
-
- julstart = JulianToday;
-
- /* If we have a skip factor of 3 (AFTER), then we must back up to
- the beginning of the block of omitted days. */
- if (skip == 3) while(julstart>=1 && IsOmitted(julstart-1, omit)) julstart--;
-
- FromJulian(julstart, &d1, &m1, &y1);
-
- /* Make a first stab at the date */
- i = TryNextDate(&d2, &m2, &y2, d1, m1, y1, d, m, y, wd, cons, 0);
- if (!i || repeat) jul = Julian(d2, m2, y2);
-
- if (!repeat && !back && !skip) {
- if (i) return -1; else return jul;
- }
-
- if (i && !repeat) return -1;
-
- while (nattempts++ < MAXATTEMPTS) {
- if (back) jul = MoveBack(jul, back, omit);
- if (repeat) {
- if (jul < julstart) {
- jul += ((julstart - jul) / repeat) * repeat;
- if (jul < julstart) jul += repeat;
- }
- }
- if (skip == 2) while (IsOmitted(jul, omit)) jul--;
- else if (skip == 3) while (IsOmitted(jul, omit)) jul++;
- if ((skip == 1 && IsOmitted(jul, omit)) || jul < JulianToday) {
- if (!repeat) {
- i = TryNextDate(&d2, &m2, &y2, d2, m2, y2, d, m, y, wd, cons, 1);
- if (i) return -1;
- jul = Julian(d2, m2, y2);
- } else {
- jul += repeat;
- back = 0; /* We've already handled the back! */
- }
- } else return jul;
- }
- Eprint("Couldn't compute a trigger date - check that date is sensible.\n");
- return -2;
- }
-