home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
pc
/
source
/
remind23.lzh
/
remind.2
/
dorem.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-02-24
|
12KB
|
427 lines
#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;
}