Path: utzoo!dciem!nrcaer!cunews!dfs From: dfs@doe.carleton.ca (David F. Skoll) Newsgroups: alt.sources Subject: REMIND 2.2 Patch 05 Summary: Adds more intelligent handling of holidays Message-ID: Date: 3 Dec 90 21:35:00 GMT Sender: news@ccs.carleton.ca (news) Organization: Carleton University, Ottawa, Canada Lines: 1160 This is the official Patch 05 for Remind version 2.2. This patch cleans up the code and man page, fixes some bugs, and adds new keywords to the program. The BEFORE, SKIP and AFTER keywords allow you to specify how to handle reminders which fall on holidays. By default, these reminders are simply triggered. Now, however, you can specify that they should be skipped, moved ahead of the holiday, or moved behind the holiday. NOTE: The definition of the 'tok' type has changed; you should do a FULL REBUILD of remind after applying this patch! Here are the steps: 1) Extract the file patch.05 from this shar. 2) Make sure you've already applied patches 1 through 4 3) Type patch < patch.05 4) Edit the Makefile if necessary 5) Type make clean 6) Type make. See the file WHATSNEW.22 or the man page after applying the patch for more details on the added features. -- David F. Skoll #!/bin/sh # This is Remind-2.2-patch.05, a shell archive (shar 3.32) # made 12/03/1990 21:32 UTC by dfs@data # Source directory /enterprise/transporter/dfs/work/.rem/remind-2.2 # # existing files will NOT be overwritten # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 32338 -rw------- patch.05 # if touch 2>&1 | fgrep 'amc' > /dev/null then TOUCH=touch else TOUCH=true fi # ============= patch.05 ============== if test X"$1" != X"-c" -a -f 'patch.05'; then echo "File already exists: skipping 'patch.05'" else echo "x - extracting patch.05 (Text)" sed 's/^X//' << 'SHAR_EOF' > patch.05 && X*** ../work/Makefile Thu Nov 29 09:10:23 1990 X--- ./Makefile Mon Dec 3 12:50:21 1990 X*************** X*** 21,27 **** X #--------------- SHOULDN'T CHANGE STUFF BELOW HERE --------------- X X all: dorem.o files.o main.o nextdate.o init.o dosubst.o timed.o calendar.o cache.o X! $(LINK.c) -o remind dorem.o files.o main.o nextdate.o init.o dosubst.o timed.o calendar.o cache.o X X dorem.o: dorem.c X X--- 21,27 ---- X #--------------- SHOULDN'T CHANGE STUFF BELOW HERE --------------- X X all: dorem.o files.o main.o nextdate.o init.o dosubst.o timed.o calendar.o cache.o X! $(CC) -o remind dorem.o files.o main.o nextdate.o init.o dosubst.o timed.o calendar.o cache.o X X dorem.o: dorem.c X X*** ../work/WHATSNEW.22 Fri Nov 16 13:22:35 1990 X--- ./WHATSNEW.22 Mon Dec 3 15:50:20 1990 X*************** X*** 10,12 **** X--- 10,19 ---- X X Version 2.2 - Added the AT keyword, the timed reminders daemon, and the X calendar facility. X+ X+ Version 2.2 - Patch 3 - Added the MSG or RUN tokens in an OMIT command; also X+ allowed RUN-type reminders to be explicitly included in the calendar by X+ using the %" escape sequence. X+ X+ Version 2.2 - Patch 5 - Added the BEFORE, AFTER and SKIP tokens to make the X+ handling of holidays more sensible. Also corrected a few more bugs. X*** ../work/cache.c Thu Nov 29 09:10:24 1990 X--- ./cache.c Mon Dec 3 12:25:04 1990 X*************** X*** 12,20 **** X #ifndef NO_MALLOC_H X #include X #endif X- #ifndef UNIX X #include X- #endif X #include "defines.h" X #include "globals.h" X #include "protos.h" X--- 12,18 ---- X*** ../work/calendar.c Thu Nov 29 09:11:53 1990 X--- ./calendar.c Mon Dec 3 12:25:15 1990 X*************** X*** 13,20 **** X #include X #endif X #include X- #ifndef UNIX X #include X #include X #endif X #include "defines.h" X--- 13,20 ---- X #include X #endif X #include X #include X+ #ifndef UNIX X #include X #endif X #include "defines.h" X*** ../work/defines.h Thu Nov 29 09:10:26 1990 X--- ./defines.h Mon Dec 3 11:09:55 1990 X*************** X*** 32,38 **** X X enum Token_t { Unknown_t, Year_t, Month_t, Day_t, WkDay_t, Msg_t, Run_t, X Omit_t, Banner_t, Rem_t, Delta_t, Back_t, Once_t, Include_t, X! Repeat_t, At_t, Time_t, Eol_t }; X X /* Define the Token structure */ X X--- 32,38 ---- X X enum Token_t { Unknown_t, Year_t, Month_t, Day_t, WkDay_t, Msg_t, Run_t, X Omit_t, Banner_t, Rem_t, Delta_t, Back_t, Once_t, Include_t, X! Repeat_t, At_t, Time_t, Skip_t, Eol_t }; X X /* Define the Token structure */ X X*************** X*** 40,45 **** X--- 40,46 ---- X char *str; X enum Token_t type; X int val; X+ char len; /* Minimum length to match */ X } Token; X X #ifdef UNIX X*** ../work/dorem.c Thu Nov 29 09:10:27 1990 X--- ./dorem.c Mon Dec 3 15:56:27 1990 X*************** X*** 1,8 **** X #include X #ifndef UNIX X #include X- #include X #endif X #include X #include "defines.h" X #include "globals.h" X--- 1,8 ---- X #include X #ifndef UNIX X #include X #endif X+ #include X #include X #include "defines.h" X #include "globals.h" X*************** X*** 25,31 **** X X #endif X { X! int d, m, y, wd, cons, delta, back, omit, done, jul, once, repeat; X int tim, tdelta, trep; X int d2, m2, y2; X Token tok; X--- 25,31 ---- X X #endif X { X! int d, m, y, wd, cons, delta, back, omit, done, jul, once, repeat, skip; X int tim, tdelta, trep; X int d2, m2, y2; X Token tok; X*************** X*** 32,38 **** X int trigger; X X d = m = y = back = delta = tim = tdelta = trep = -1; X! repeat = cons = wd = omit = once = 0; X X X done = 0; X--- 32,38 ---- X int trigger; X X d = m = y = back = delta = tim = tdelta = trep = -1; X! repeat = cons = wd = omit = once = skip = 0; X X X done = 0; X*************** X*** 48,53 **** X--- 48,61 ---- X case Run_t: X case Msg_t: done = 1; break; X X+ case Skip_t: X+ if (skip) { X+ Eprint("Can only have one of BEFORE, AFTER or SKIP.\n"); X+ return 0; X+ } X+ skip = tok.val; X+ break; X+ X case Unknown_t: X Eprint("Unknown token %s in reminder.\n", tok.str); X return 0; X*************** X*** 205,214 **** X--- 213,228 ---- X } X X X+ /* Do some sanity checking on the reminder */ X if (repeat && (d == -1 || m == -1 || y == -1)) { X Eprint("Can't use repeat counter unless you fully specify the date.\n"); X return 0; X } X+ X+ if (skip && (wd & omit)) { X+ Eprint("Conflict between weekday list and local OMIT\n"); X+ return 0; X+ } X X if (d != -1 && m != -1 && CheckDate(d, m, y)) { X Eprint("Illegal date specification.\n"); X*************** X*** 240,246 **** X if (back == -1) back = 0; X if (delta == -1) delta = 0; X X! jul = GetTriggerDate(d, m, y, wd, cons, back, repeat, omit); X if (Calendar) { X if (jul == JulianToday) { X while (isspace(**s)) (*s)++; X--- 254,260 ---- X if (back == -1) back = 0; X if (delta == -1) delta = 0; X X! jul = GetTriggerDate(d, m, y, wd, cons, back, repeat, omit, skip); X if (Calendar) { X if (jul == JulianToday) { X while (isspace(**s)) (*s)++; X*************** X*** 253,264 **** X if (jul == -1) { X if (Debug) Eprint("Reminder has expired.\n"); X return -1; X! } X FromJulian(jul, &d2, &m2, &y2); X X /* Figure out if the reminder should be triggered */ X X! trigger = MoveBack(jul, delta, d2, m2, y2, omit); X X if(Debug) { X Eprint("%sTrigger date: %s, %d %s, %d.\n", X--- 267,279 ---- X if (jul == -1) { X if (Debug) Eprint("Reminder has expired.\n"); X return -1; X! } else if (jul == -2) return 0; X! X FromJulian(jul, &d2, &m2, &y2); X X /* Figure out if the reminder should be triggered */ X X! trigger = MoveBack(jul, delta, omit); X X if(Debug) { X Eprint("%sTrigger date: %s, %d %s, %d.\n", X*************** X*** 304,347 **** X /* */ X /* Gets the trigger date for a reminder, returns the julian */ X /* date, or -1 if the reminder has expired. */ X /* */ X /***************************************************************/ X #ifndef UNIX X! int GetTriggerDate(int d, int m, int y, int wd, int cons, int back, int repeat, int omit) X #else X! int GetTriggerDate(d, m, y, wd, cons, back, repeat, omit) X! int d, m, y, wd, cons, back, repeat, omit; X #endif X { X int i, d2, m2, y2, jul; X X! i = TryNextDate(&d2, &m2, &y2, CurDay, CurMon, CurYear, X! d, m, y, wd, cons, 0); X X! if (i && !repeat) return -1; X X jul = Julian(d2, m2, y2); X! if (repeat) { X! if (back) jul = MoveBack(jul, back, d2, m2, y2, omit); X X! if (jul < JulianToday) { X! jul += ((JulianToday - jul) / repeat) * repeat; X! if (jul < JulianToday) jul += repeat; X! } X! return jul; X X! } else { X! if (back) { X! jul = MoveBack(jul, back, d2, m2, y2, omit); X! while (jul < JulianToday) { X! i = TryNextDate(&d2, &m2, &y2, d2, m2, y2, X! d, m, y, wd, cons, 1); X! if (i) return -1; X! jul = Julian(d2, m2, y2); X! jul = MoveBack(jul, back, d2, m2, y2, omit); X } X- X } X! return jul; X } X } X--- 319,379 ---- X /* */ X /* Gets the trigger date for a reminder, returns the julian */ X /* date, or -1 if the reminder has expired. */ X+ /* Returns -2 if an error occurs. */ X /* */ X /***************************************************************/ X #ifndef UNIX X! int GetTriggerDate(int d, int m, int y, int wd, int cons, int back, int repeat, int omit, int skip) X #else X! int GetTriggerDate(d, m, y, wd, cons, back, repeat, omit, skip) X! int d, m, y, wd, cons, back, repeat, omit, skip; X #endif X+ #define MAXATTEMPTS 25 /* Maximum number of attempts before giving up */ X+ X { X int i, d2, m2, y2, jul; X+ int d1, m1, y1, julstart; X+ int nattempts = 0; X X! julstart = JulianToday; X X! /* If we have a skip factor of 3 (AFTER), then we must back up to X! the beginning of the block of omitted days. */ X! if (skip == 3) while(julstart>=1 && IsOmitted(julstart-1, omit)) julstart--; X X+ FromJulian(julstart, &d1, &m1, &y1); X+ X+ /* Make a first stab at the date */ X+ i = TryNextDate(&d2, &m2, &y2, d1, m1, y1, d, m, y, wd, cons, 0); X jul = Julian(d2, m2, y2); X! X! if (!repeat && !back && !skip) { X! if (i) return -1; else return jul; X! } X X! if (i && !repeat) return -1; X X! while (nattempts++ < MAXATTEMPTS) { X! if (back) jul = MoveBack(jul, back, omit); X! if (repeat) { X! if (jul < julstart) { X! jul += ((julstart - jul) / repeat) * repeat; X! if (jul < julstart) jul += repeat; X } X } X! if (skip == 2) while (IsOmitted(jul, omit)) jul--; X! else if (skip == 3) while (IsOmitted(jul, omit)) jul++; X! if ((skip == 1 && IsOmitted(jul, omit)) || jul < JulianToday) { X! if (!repeat) { X! i = TryNextDate(&d2, &m2, &y2, d2, m2, y2, d, m, y, wd, cons, 1); X! if (i) return -1; X! jul = Julian(d2, m2, y2); X! } else { X! jul += repeat; X! back = 0; /* We've already handled the back! */ X! } X! } else return jul; X } X+ Eprint("Couldn't compute a trigger date - check that date is sensible.\n"); X+ return -2; X } X*** ../work/dosubst.c Fri Nov 16 09:57:14 1990 X--- ./dosubst.c Mon Dec 3 12:26:31 1990 X*************** X*** 1,8 **** X #include X #include X- #ifndef UNIX X #include X- #endif X #include "defines.h" X #include "globals.h" X #include "protos.h" X--- 1,6 ---- X*** ../work/files.c Thu Nov 29 09:10:28 1990 X--- ./files.c Mon Dec 3 14:16:03 1990 X*************** X*** 203,209 **** X if (!SP) { X if (!Debug && !Purge && (JulianToday == RealToday)) { X if (_dos_open(FileName, O_RDONLY, &handle)) { X! fprintf(stderr, "Could not reset date of %s", FileName); X return 1; X } X _dos_gettime(&t); X--- 203,209 ---- X if (!SP) { X if (!Debug && !Purge && (JulianToday == RealToday)) { X if (_dos_open(FileName, O_RDONLY, &handle)) { X! fprintf(stderr, "Could not reset date of %s\n", FileName); X return 1; X } X _dos_gettime(&t); X*************** X*** 225,231 **** X SP--; X fp = fopen(stack[SP].name, "r"); X if (fp == NULL) { X! Eprint("Argh! Can't return to %s from INCLUDE file %s", stack[SP].name, FileName); X exit(1); X } X #ifndef UNIX X--- 225,231 ---- X SP--; X fp = fopen(stack[SP].name, "r"); X if (fp == NULL) { X! Eprint("Argh! Can't return to %s from INCLUDE file %s\n", stack[SP].name, FileName); X exit(1); X } X #ifndef UNIX X*************** X*** 233,239 **** X #else X if (fseek(fp, stack[SP].offset, 0)) { X #endif X! Eprint("Argh! Can't fseek %s after returning from INCLUDE file %s", stack[SP].name, FileName); X exit(1); X } X X--- 233,239 ---- X #else X if (fseek(fp, stack[SP].offset, 0)) { X #endif X! Eprint("Argh! Can't fseek %s after returning from INCLUDE file %s\n", stack[SP].name, FileName); X exit(1); X } X X*************** X*** 263,269 **** X while (!done) { X CurLine++; X if (fgets(Line, 512, fp) == NULL) { X! if (ferror(fp)) Eprint("Error reading %s", FileName); X if (PopFile()) return 1; X } else { X len = strlen(Line); X--- 263,269 ---- X while (!done) { X CurLine++; X if (fgets(Line, 512, fp) == NULL) { X! if (ferror(fp)) Eprint("Error reading %s\n", FileName); X if (PopFile()) return 1; X } else { X len = strlen(Line); X*** ../work/init.c Thu Nov 29 09:12:03 1990 X--- ./init.c Fri Nov 30 14:07:02 1990 X*************** X*** 7,13 **** X #include "globals.h" X #include "protos.h" X X! #define PATCHLEVEL 4 X X static char DPMsg[] = "Debug and Purge options conflict - Purge chosen.\n"; X static char DPCMsg[] = "Calendar overrides Debug and Purge options.\n"; X--- 7,13 ---- X #include "globals.h" X #include "protos.h" X X! #define PATCHLEVEL 5 X X static char DPMsg[] = "Debug and Purge options conflict - Purge chosen.\n"; X static char DPCMsg[] = "Calendar overrides Debug and Purge options.\n"; X*** ../work/main.c Thu Nov 29 09:10:30 1990 X--- ./main.c Mon Dec 3 15:35:57 1990 X*************** X*** 24,29 **** X--- 24,30 ---- X #include X #endif X #endif X+ X #include "defines.h" X #include "protos.h" X X*************** X*** 42,74 **** X /* List of recognized tokens */ X X Token keywd[] = { X! { "BANNER", Banner_t, 0 }, X! { "OMIT", Omit_t, 0 }, X! { "REM", Rem_t, 0 }, X! { "January", Month_t, 0 }, X! { "February", Month_t, 1 }, X! { "March", Month_t, 2 }, X! { "April", Month_t, 3 }, X! { "May", Month_t, 4 }, X! { "June", Month_t, 5 }, X! { "July", Month_t, 6 }, X! { "August", Month_t, 7 }, X! { "September", Month_t, 8 }, X! { "October", Month_t, 9 }, X! { "November", Month_t, 10 }, X! { "December", Month_t, 11 }, X! { "Monday", WkDay_t, 0 }, X! { "Tuesday", WkDay_t, 1 }, X! { "Wednesday", WkDay_t, 2 }, X! { "Thursday", WkDay_t, 3 }, X! { "Friday", WkDay_t, 4 }, X! { "Saturday", WkDay_t, 5 }, X! { "Sunday", WkDay_t, 6 }, X! { "MSG", Msg_t, 0 }, X! { "RUN", Run_t, 0 }, X! { "ONCE", Once_t, 0 }, X! { "INCLUDE", Include_t, 0}, X! { "AT", At_t, 0} X }; X X /* List of days in month - Feb MUST be 29 for CheckDate to work. */ X--- 43,78 ---- X /* List of recognized tokens */ X X Token keywd[] = { X! { "BANNER", Banner_t, 0, 3 }, X! { "OMIT", Omit_t, 0, 3 }, X! { "REM", Rem_t, 0, 3 }, X! { "January", Month_t, 0, 3 }, X! { "February", Month_t, 1, 3 }, X! { "March", Month_t, 2, 3 }, X! { "April", Month_t, 3, 3 }, X! { "May", Month_t, 4, 3 }, X! { "June", Month_t, 5, 3 }, X! { "July", Month_t, 6, 3 }, X! { "August", Month_t, 7, 3 }, X! { "September", Month_t, 8, 3 }, X! { "October", Month_t, 9, 3 }, X! { "November", Month_t, 10, 3 }, X! { "December", Month_t, 11, 3 }, X! { "Monday", WkDay_t, 0, 3 }, X! { "Tuesday", WkDay_t, 1, 3 }, X! { "Wednesday", WkDay_t, 2, 3 }, X! { "Thursday", WkDay_t, 3, 3 }, X! { "Friday", WkDay_t, 4, 3 }, X! { "Saturday", WkDay_t, 5, 3 }, X! { "Sunday", WkDay_t, 6, 3 }, X! { "MSG", Msg_t, 0, 3 }, X! { "RUN", Run_t, 0, 3 }, X! { "ONCE", Once_t, 0, 3 }, X! { "INCLUDE", Include_t, 0, 3 }, X! { "AT", At_t, 0, 2 }, X! { "SKIP", Skip_t, 1, 3 }, X! { "BEFORE", Skip_t, 2, 3 }, X! { "AFTER", Skip_t, 3, 3 } X }; X X /* List of days in month - Feb MUST be 29 for CheckDate to work. */ X*************** X*** 109,122 **** X X static int JulFirst; /* Julian date of 1 Jan Current_year */ X static int FirstYear; X- #ifndef UNIX X- int int_comp(int *a, int *b) { return *a - *b; } X- #else X- int int_comp(a, b) X- int *a; X- int *b; X- { return *a - *b; } X- #endif X X /***************************************************************/ X /* */ X--- 113,118 ---- X*************** X*** 146,159 **** X /* */ X /***************************************************************/ X #ifndef UNIX X! int MoveBack (int jul, int back, int d, int m, int y, int omit) X #else X! int MoveBack (jul, back, d, m, y, omit) X int jul; X int back; X- int d; X- int m; X- int y; X int omit; X #endif X { X--- 142,152 ---- X /* */ X /***************************************************************/ X #ifndef UNIX X! int MoveBack (int jul, int back, int omit) X #else X! int MoveBack (jul, back, omit) X int jul; X int back; X int omit; X #endif X { X*************** X*** 162,186 **** X if (!NumFullOmit && !NumPartOmit && !omit) return jul - back; X while (back) { X jul--; X! if (omit & 1 << (jul % 7)) continue; /* Omitted due to weekday */ X! X! /* Omit if in fully-specified omit list */ X! if (NumFullOmit && bsearch(&jul, FullOmitArray, NumFullOmit, sizeof(int), int_comp)) continue; X! X! if (NumPartOmit) { X! d--; X! if (d == 0) { X! m--; X! if (m < 0) { X! y--; X! m = 11; X! } X! d = DaysInMonth(m, y); X! } X! temp = (m << 5) + d; X! if (bsearch(&temp, PartOmitArray, NumPartOmit, sizeof(int), int_comp)) continue; X! } X! back--; X } X return jul; X } X--- 155,161 ---- X if (!NumFullOmit && !NumPartOmit && !omit) return jul - back; X while (back) { X jul--; X! if (!IsOmitted(jul, omit)) back--; X } X return jul; X } X*************** X*** 427,436 **** X return -2; X } X omit = Julian(d, m, y); X- if (omit < JulianToday) { X- if (Debug) Eprint("Omit has expired.\n"); X- return -1; X- } X X ptr = FullOmitArray + NumFullOmit; X NumFullOmit++; X--- 402,407 ---- X*************** X*** 449,454 **** X--- 420,429 ---- X ptr++; X } X } X+ if (omit < JulianToday) { X+ if (Debug) Eprint("Omit has expired.\n"); X+ return -1; X+ } X /* If we got a MSG or a RUN, then execute DoRem */ X if (tok.type == Run_t || tok.type == Msg_t) return DoRem(&olds); X } X*************** X*** 529,542 **** X X /* Check if it's a built-in token */ X for (i=0; i < sizeof(keywd)/sizeof(keywd[0]); i++) X! if (len >= 3 && !strncmpi(TmpBuf, keywd[i].str, len)) return keywd[i]; X X- /* ARGH. Check for "AT" as special case: < 3 chars */ X- if (len == 2 && !strncmpi(TmpBuf, "AT", 2)) { X- tok.type = At_t; X- return tok; X- } X- X tok.type = Unknown_t; X X /* If it's a comment, ignore the rest of the line */ X--- 504,511 ---- X X /* Check if it's a built-in token */ X for (i=0; i < sizeof(keywd)/sizeof(keywd[0]); i++) X! if (len >= keywd[i].len && !strncmpi(TmpBuf, keywd[i].str, len)) return keywd[i]; X X tok.type = Unknown_t; X X /* If it's a comment, ignore the rest of the line */ X*************** X*** 545,551 **** X return tok; X } X X! /* Check if it's a number (optional +/-/* ahead of number */ X t = TmpBuf; X if (isdigit(*t)) { X while (*++t){ X--- 514,520 ---- X return tok; X } X X! /* Check if it's a number (optional + / - / * ahead of number */ X t = TmpBuf; X if (isdigit(*t)) { X while (*++t){ X*************** X*** 713,719 **** X if (CheckDate(*d, *m, *y)) return -1; X return Julian(*d, *m, *y); X } X! X #ifndef UNIX X int main(int argc, char *argv[]) X #else X--- 682,694 ---- X if (CheckDate(*d, *m, *y)) return -1; X return Julian(*d, *m, *y); X } X! /***************************************************************/ X! /***************************************************************/ X! /** **/ X! /** MAIN PROGRAM ENTRY POINT **/ X! /** **/ X! /***************************************************************/ X! /***************************************************************/ X #ifndef UNIX X int main(int argc, char *argv[]) X #else X*************** X*** 773,778 **** X--- 748,754 ---- X HandleQueuedAts(); X } X #endif X+ return 0; X } X /***************************************************************/ X /* */ X*************** X*** 800,803 **** X--- 776,842 ---- X _dos_gettime(&tloc); X return (long) tloc.hour * 3600L + (long) tloc.minute * 60L + (long) tloc.second; X #endif X+ } X+ /***************************************************************/ X+ /* */ X+ /* my_bsearch */ X+ /* */ X+ /* A simplified version of bsearch() for people whose library */ X+ /* does not have the full version. This only works when */ X+ /* searching a sorted array of integers. */ X+ /* */ X+ /***************************************************************/ X+ #ifndef UNIX X+ int *my_bsearch(int key, int *array, int number) X+ #else X+ int *my_bsearch(key, array, number) X+ int key, *array, number; X+ #endif X+ { X+ int top = number - 1; X+ int bot = 0; X+ int mid; X+ X+ while (top >= bot) { X+ mid = (top+bot)/2; X+ if (*(array+mid) == key) return array+mid; X+ else if (*(array+mid) > key) top = mid-1; X+ else bot = mid+1; X+ } X+ X+ /* Oh, well - unsuccessful search. Return NULL */ X+ return NULL; X+ } X+ X+ /***************************************************************/ X+ /* */ X+ /* IsOmitted */ X+ /* */ X+ /* Returns non-zero if the julian date should be omitted, 0 */ X+ /* otherwise. */ X+ /* */ X+ /***************************************************************/ X+ #ifndef UNIX X+ int IsOmitted(int jul, int localomit) X+ #else X+ int IsOmitted(jul, localomit) X+ int jul, localomit; X+ #endif X+ { X+ int d, m, y; X+ X+ /* Check if we should omit because of local omit */ X+ if (localomit & 1 << (jul % 7)) return 1; X+ X+ /* Check if we should omit because of fully-specified global omit */ X+ if (NumFullOmit && my_bsearch(jul, FullOmitArray, NumFullOmit)) return 1; X+ X+ /* Check if we should omit because of partially-specified global omits */ X+ if (NumPartOmit) { X+ FromJulian(jul, &d, &m, &y); X+ if (my_bsearch((m << 5)+d, PartOmitArray, NumPartOmit)) return 1; X+ } X+ X+ /* Looks cool - don't omit */ X+ return 0; X } X*** ../work/protos.h Thu Nov 15 09:58:04 1990 X--- ./protos.h Mon Dec 3 14:17:47 1990 X*************** X*** 12,23 **** X void Eprint(const char *f, ...); X int FindTodaysDate(int *d, int *m, int *y); X int FromJulian (int jul, int *d, int *m, int *y); X! int GetTriggerDate (int d, int m, int y, int wd, int cons, int back, int repeat, int omit); X void HandleQueuedAts(void); X void initialize (int argc, char *argv[]); X int int_comp (int *, int *); X int Julian (int d, int m, int y); X! int MoveBack (int jul, int back, int d, int m, int y, int omit); X void OpenFile (char *s); X void Output (char *s); X Token ParseToken (char **s); X--- 12,25 ---- X void Eprint(const char *f, ...); X int FindTodaysDate(int *d, int *m, int *y); X int FromJulian (int jul, int *d, int *m, int *y); X! int GetTriggerDate (int d, int m, int y, int wd, int cons, int back, int repeat, int omit, int skip); X! int IsOmitted (int jul, int localomit); X void HandleQueuedAts(void); X void initialize (int argc, char *argv[]); X int int_comp (int *, int *); X int Julian (int d, int m, int y); X! int MoveBack (int jul, int back, int omit); X! int *my_bsearch (int key, int *array, int number); X void OpenFile (char *s); X void Output (char *s); X Token ParseToken (char **s); X*************** X*** 41,51 **** X--- 43,55 ---- X int FindTodaysDate(); X int FromJulian (); X int GetTriggerDate(); X+ int IsOmitted (); X void HandleQueuedAts(); X void initialize (); X int int_comp (); X int Julian (); X int MoveBack (); X+ int *my_bsearch (); X void OpenFile (); X void Output (); X Token ParseToken (); X*** ../work/remind.1 Thu Nov 29 09:12:19 1990 X--- ./remind.1 Mon Dec 3 16:28:48 1990 X*************** X*** 1,4 **** X! .TH REMIND 1 "25 October 1990" X .UC 4 X .SH NAME X remind \- a sophisticated reminder service X--- 1,4 ---- X! .TH REMIND 1 "29 November 1990" X .UC 4 X .SH NAME X remind \- a sophisticated reminder service X*************** X*** 158,165 **** X REM 1 -1 OMIT Sat Sun RUN do_backup X X # Introduce some holidays X! OMIT 25 Dec # Christmas X! OMIT 1 July # Canada Day X OMIT 22 Nov 1990 # American Thanksgiving X X # Business things X--- 158,165 ---- X REM 1 -1 OMIT Sat Sun RUN do_backup X X # Introduce some holidays X! OMIT 25 Dec +2 MSG %"Christmas%" is %b. X! OMIT 1 July MSG Canada Day X OMIT 22 Nov 1990 # American Thanksgiving X X # Business things X*************** X*** 201,206 **** X--- 201,207 ---- X [\fIdelta\fR] X [\fIback\fR] X [\fIrepeat\fR] X+ [\fISKIP\fR | \fIBEFORE\fR | \fIAFTER\fR] X [OMIT \fIomit_list\fR] X [AT \fItime\fR [\fItdelta\fR] [\fItrepeat\fR]] X [MSG | RUN] X*************** X*** 208,219 **** X .RE X .PP X The X! .I date_spec, delta, back X and X! .I repeat X can be specified in any order. The X .I OMIT, X! if present, must follow these three X items. The X .I AT, X if present, must follow the X--- 209,220 ---- X .RE X .PP X The X! .I date_spec, delta, back, repeat, SKIP, BEFORE X and X! .I AFTER X can be specified in any order. The X .I OMIT, X! if present, must follow these X items. The X .I AT, X if present, must follow the X*************** X*** 349,355 **** X present. Examples: X .nf X REM Sat 1 MSG First Saturday of every month X! REM Mon Tue Wed Thu Fri MSG 1st working day after 15th of every month X .fi X .PP X 11. X--- 350,357 ---- X present. Examples: X .nf X REM Sat 1 MSG First Saturday of every month X! REM Mon Tue Wed Thu Fri 15 \\ X! MSG 1st working day after 15th of every month X .fi X .PP X 11. X*************** X*** 388,395 **** X present. Examples: X .nf X REM Mon 15 1990 MSG 1st Mon after 15th of every month in 1990 X! REM Mon Tue Wed Thu Fri 1 1990 MSG 1st working day of every X! month in 1990 X .fi X .PP X 15. X--- 390,397 ---- X present. Examples: X .nf X REM Mon 15 1990 MSG 1st Mon after 15th of every month in 1990 X! REM Mon Tue Wed Thu Fri 1 1990 \\ X! MSG 1st working day of every month in 1990 X .fi X .PP X 15. X*************** X*** 407,414 **** X .I year X present. Example: X .nf X! REM Mon Tue Wed Thu Fri 28 Oct 1990 MSG 1st working day X! on or after 28 October 1990. X .fi X .PP X Note that when X--- 409,416 ---- X .I year X present. Example: X .nf X! REM Mon Tue Wed Thu Fri 28 Oct 1990 \\ X! MSG 1st working day on or after 28 October 1990. X .fi X .PP X Note that when X*************** X*** 556,563 **** X when calculating the trigger date. The final trigger date is strictly X a multiple of X .I repeat X! days from the start date. X .PP X .B THE MSG KEYWORD X .PP X The X--- 558,625 ---- X when calculating the trigger date. The final trigger date is strictly X a multiple of X .I repeat X! days from the start date. The only exceptions are those cases covered X! by the \fIBEFORE, AFTER\fR and \fISKIP\fR keywords, discussed in the X! next section. X .PP X+ .B THE BEFORE, AFTER AND SKIP KEYWORDS X+ .PP X+ Should a reminder's trigger date happen to fall on an OMITted day, the X+ default action is to go ahead and trigger the reminder anyway. For example, X+ suppose you have a meeting every Tuesday. Consider the following: X+ .PP X+ .nf X+ OMIT 1 Jan MSG New Year's Day X+ OMIT 25 December MSG Christmas X+ REM Tue AT 13:00 MSG Code review meeting. X+ .fi X+ .PP X+ Even though Christmas 1990 is on a Tuesday, you will still be reminded X+ of a code review meeting on that day. Surely that is not desirable. You X+ can tell \fBremind\fR to skip reminders which fall on OMITted days with the X+ .I SKIP X+ keyword. Assuming we have the same \fIOMIT\fR commands, then: X+ .PP X+ .nf X+ REM Tue SKIP AT 13:00 MSG Code review meeting. X+ .fi X+ .PP X+ would be triggered every Tuesday, but not on Christmas or New Year's X+ Day, because both of these holidays happen to fall on Tuesdays. X+ .PP X+ In some situations, we don't want to skip the reminder; we want to move X+ it to just before or just after a holiday. Consider these examples: X+ .PP X+ .nf X+ REM Fri AFTER OMIT Sat Sun MSG Do your backup! X+ .fi X+ .PP X+ This reminder is normally triggered every Friday. However, if a particular X+ Friday happens to be a holiday, it will be triggered on the Monday after X+ the holiday instead. Note that the \fIAFTER\fR keyword keeps scanning X+ forwards until it hits a day which is not in the global or local \fIOMIT\fR X+ lists. (Of course, if both the Friday and Monday are holidays, then the X+ reminder would be deferred until Tuesday, and so on.) X+ .PP X+ .nf X+ REM Fri BEFORE MSG Do your backup! X+ .fi X+ .PP X+ This is similar, except that the reminder is issued on the previous Thursday X+ if a particular Friday happens to be a holiday. This form, too, will X+ move back to Wednesday if Thursday also happens to be a holiday, and so on. X+ .PP X+ Note: These keywords skip both local and global \fIOMIT\fRs. Also, X+ \fBremind\fR will complain about certain illegal constructions, such as: X+ .PP X+ .nf X+ REM Mon SKIP OMIT Mon MSG Impossible! X+ .fi X+ .PP X+ If \fBremind\fR makes too many attempts to find a trigger date for X+ certain forms, it assumes that no satisfiable date exists, and will warn X+ you to check the date specification. In practice, this should never happen. X+ .PP X .B THE MSG KEYWORD X .PP X The X*************** X*** 860,869 **** X--- 922,933 ---- X The X .I INCLUDE X command has the following form: X+ .PP X .RS X INCLUDE X .I filename X .RE X+ .PP X This causes X .B remind X to suspend the current file and read the contents of the specified X*************** X*** 905,912 **** X Before being processed, the body of a X .I REM X command is passed through a substitution filter. The filter scans for X! sequences "%x" where "x" is any letter and certain other characters, X! and performs substitutions as X shown below. (All dates refer to the trigger date of the reminder.) X .TP X .B %a X--- 969,976 ---- X Before being processed, the body of a X .I REM X command is passed through a substitution filter. The filter scans for X! sequences "%x" (where "x" is any letter and certain other characters) X! and performs substitutions as X shown below. (All dates refer to the trigger date of the reminder.) X .TP X .B %a X*************** X*** 1196,1202 **** X will get many error messages apparently coming from the file "*cache*" X This is because \fBremind\fR caches the reminder file for efficient X production of the calendar. Thus, you should check that your reminder X! file is error-free (by running \fBremind\fR with the \fB\-\d\fR option) X before attempting to produce a calendar. X .SH THE BANNER COMMAND X When X--- 1260,1266 ---- X will get many error messages apparently coming from the file "*cache*" X This is because \fBremind\fR caches the reminder file for efficient X production of the calendar. Thus, you should check that your reminder X! file is error-free (by running \fBremind\fR with the \fB\-d\fR option) X before attempting to produce a calendar. X .SH THE BANNER COMMAND X When X*************** X*** 1332,1334 **** X--- 1396,1403 ---- X The MS-DOS version of \fBremind\fR does not support queuing or timed X activation of reminders. It does, however, support the other semantics X of the \fIAT\fR keyword. X+ .PP X+ .B Remind X+ has some built-in limits on total line length (511 characters), X+ the length of an expanded \fIREM\fR body (511 characters), the number X+ of global \fIOMIT\fRs, etc. X*** ../work/timed.c Thu Nov 29 09:10:32 1990 X--- ./timed.c Mon Dec 3 12:24:41 1990 X*************** X*** 1,5 **** X--- 1,6 ---- X #include X #include X+ #include X #ifndef NO_MALLOC_H X #include X #endif SHAR_EOF $TOUCH -am 1203163090 patch.05 && chmod 0600 patch.05 || echo "restore of patch.05 failed" set `wc -c patch.05`;Wc_c=$1 if test "$Wc_c" != "32338"; then echo original size 32338, current size $Wc_c fi fi exit 0 Brought to you by Super Global Mega Corp .com