[alt.sources] REMIND 2.1

dfs@doe.carleton.ca (David F. Skoll) (11/07/90)

The following patches convert Remind 2.0 to Remind 2.1

The first file (patch.01) was posted earlier.  It corrects the
bug which caused remind to print "23th" instead of "23rd".  If
you've already applied this patch, simply proceed with patch.02

The second patch adds the "repeating reminder" feature.  This allows
you to have a reminder which repeats with an arbitrary period, rather
than weekly, monthly, etc.  See the man page for more information.

To apply the patches:

o Extract the shar archive in the REMIND build directory

o Apply the patches (eg: cat patch.* | patch)

o Type make

o Re-install the new version of remind and the updated man page.

--------------- CUT HERE FOR PATCHES ARCHIVE ---------------
#!/bin/sh
# This is Patches for Remind 2.0, a shell archive (shar 3.32)
# made 11/06/1990 21:03 UTC by dfs@chekov
# Source directory /enterprise/navigation/dfs/work/.rem/remind-2.0
#
# existing files will NOT be overwritten
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   1026 -rw------- patch.01
#  12130 -rw------- patch.02
#
if touch 2>&1 | fgrep 'amc' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= patch.01 ==============
if test X"$1" != X"-c" -a -f 'patch.01'; then
	echo "File already exists: skipping 'patch.01'"
else
echo "x - extracting patch.01 (Text)"
sed 's/^X//' << 'SHAR_EOF' > patch.01 &&
X*** main.c	Fri Nov  2 12:26:17 1990
X--- ../merged/main.c	Mon Nov  5 10:19:13 1990
X***************
X*** 282,288 ****
X     if (! *Banner)
X     {
X        if (Debug) Eprint("Empty banner.\n");
X!       strcpy(Banner, "Reminders for %d %m, %y%o:");
X     }
X     if (NumRem && Debug) Eprint("Warning: Banner after reminder.\n");
X     return 0;
X--- 282,288 ----
X     if (! *Banner)
X     {
X        if (Debug) Eprint("Empty banner.\n");
X!       strcpy(Banner, "Reminders for %w, %d%s %m, %y%o:");
X     }
X     if (NumRem && Debug) Eprint("Warning: Banner after reminder.\n");
X     return 0;
X*** dosubst.c	Fri Nov  2 12:26:13 1990
X--- ../merged/dosubst.c	Mon Nov  5 10:18:04 1990
X***************
X*** 51,57 ****
X        case 2:
X        case 22: plu = "nd"; break;
X        
X!       case 3:  plu = "rd"; break;
X        
X        default: plu = "th"; break;
X     }
X--- 51,58 ----
X        case 2:
X        case 22: plu = "nd"; break;
X        
X!       case 3:
X!       case 23: plu = "rd"; break;
X        
X        default: plu = "th"; break;
X     }
SHAR_EOF
$TOUCH -am 1106155890 patch.01 &&
chmod 0600 patch.01 ||
echo "restore of patch.01 failed"
set `wc -c patch.01`;Wc_c=$1
if test "$Wc_c" != "1026"; then
	echo original size 1026, current size $Wc_c
fi
fi
# ============= patch.02 ==============
if test X"$1" != X"-c" -a -f 'patch.02'; then
	echo "File already exists: skipping 'patch.02'"
else
echo "x - extracting patch.02 (Text)"
sed 's/^X//' << 'SHAR_EOF' > patch.02 &&
X*** ../remind-2.0-patch1/defines.h	Tue Nov  6 15:53:25 1990
X--- defines.h	Tue Nov  6 14:48:17 1990
X***************
X*** 30,36 ****
X  #define WKDAY_M 8
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, Eol_t };
X  			   
X  /* Define the Token structure */
X  
X--- 30,37 ----
X  #define WKDAY_M 8
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, Eol_t };
X  			   
X  /* Define the Token structure */
X  
X*** ../remind-2.0-patch1/dorem.c	Tue Nov  6 15:53:25 1990
X--- dorem.c	Tue Nov  6 15:15:03 1990
X***************
X*** 24,36 ****
X       
X  #endif UNIX
X  {
X!    int d, m, y, wd, cons, delta, back, omit, done, i, jul, once;
X     int d2, m2, y2;
X     Token tok;
X     int trigger;
X  
X     d = m = y = back = delta = -1;
X!    cons = wd = omit = once = 0;
X  
X  
X     done = 0;
X--- 24,36 ----
X       
X  #endif UNIX
X  {
X!   int d, m, y, wd, cons, delta, back, omit, done, i, jul, once, repeat;
X     int d2, m2, y2;
X     Token tok;
X     int trigger;
X  
X     d = m = y = back = delta = -1;
X!    repeat = cons = wd = omit = once = 0;
X  
X  
X     done = 0;
X***************
X*** 49,54 ****
X--- 49,66 ----
X  	    Eprint("Unknown token %s in reminder.\n", tok.str);
X  	    return 0;
X  
X+          case Repeat_t:
X+             if (repeat) {
X+                Eprint("Repeat factor specified twice.\n");
X+                return 0;
X+             }
X+             repeat = tok.val;
X+             if (repeat <= 0) {
X+                Eprint("Invalid value for repeat factor: %d\n", repeat);
X+                return 0;
X+             }
X+             break;
X+ 
X  	 case Banner_t:
X  	    Eprint("BANNER can't be used here.\n");
X  	    return 0;
X***************
X*** 143,150 ****
X  	    default:
X  	       Eprint("Only weekdays are valid after a local OMIT.\n");
X  	       return 0;
X! 	 }
X!       }
X     }
X     
X     if (d != -1 && m != -1 && CheckDate(d, m, y)) {
X--- 155,167 ----
X  	    default:
X  	       Eprint("Only weekdays are valid after a local OMIT.\n");
X  	       return 0;
X!            }
X!        }
X!     }
X! 
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 (d != -1 && m != -1 && CheckDate(d, m, y)) {
X***************
X*** 175,181 ****
X  
X     i = TryNextDate(&d2, &m2, &y2, CurDay, CurMon, CurYear,
X  		   d, m, y, wd, cons, 0);
X!    if (i) {
X        if (Debug) Eprint("Reminder has expired.\n");
X        return -1;
X     }
X--- 192,198 ----
X  
X     i = TryNextDate(&d2, &m2, &y2, CurDay, CurMon, CurYear,
X  		   d, m, y, wd, cons, 0);
X!    if (i && !repeat) {
X        if (Debug) Eprint("Reminder has expired.\n");
X        return -1;
X     }
X***************
X*** 185,203 ****
X     if (delta == -1) delta = 0;
X  
X     jul = Julian(d2, m2, y2);
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) {
X! 	    if (Debug) Eprint("Reminder has expired.\n");
X! 	    return -1;
X! 	 }
X!          jul = Julian(d2, m2, y2);
X! 	 jul = MoveBack(jul, back, d2, m2, y2, omit);
X        }
X-       FromJulian(jul, &d2, &m2, &y2);
X     }
X     
X     /* Figure out if the reminder should be triggered */
X--- 202,231 ----
X     if (delta == -1) delta = 0;
X  
X     jul = Julian(d2, m2, y2);
X!    if (repeat) {
X!       if (back) {
X!          jul = MoveBack(jul, back, d2, m2, y2, omit);
X!          FromJulian(jul, &d2, &m2, &y2);
X!       }
X!       if (jul < JulianToday) {
X!          jul += ((JulianToday - jul) / repeat) * repeat + repeat;
X!          FromJulian(jul, &d2, &m2, &y2);
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) {
X! 	       if (Debug) Eprint("Reminder has expired.\n");
X! 	       return -1;
X! 	    }
X!             jul = Julian(d2, m2, y2);
X! 	    jul = MoveBack(jul, back, d2, m2, y2, omit);
X!          }
X!          FromJulian(jul, &d2, &m2, &y2);
X        }
X     }
X     
X     /* Figure out if the reminder should be triggered */
X***************
X*** 212,218 ****
X     }
X     if (Purge || (once && (LastRun == JulianToday))) return 0;
X     while (isspace(**s)) (*s)++;
X!    if (trigger <= JulianToday && !(tok.type == Run_t && IgRun)) { /* Trigger a reminder */
X        if (NumEmitted == 0 && !Purge && !Debug) {
X           DoSubst(Banner, WorkBuf, CurDay, CurMon, CurYear, JulianToday, Msg_t);
X  	 printf("%s\n", WorkBuf);
X--- 240,247 ----
X     }
X     if (Purge || (once && (LastRun == JulianToday))) return 0;
X     while (isspace(**s)) (*s)++;
X!    if (trigger <= JulianToday && !(tok.type == Run_t && IgRun)) { 
X!       /* Trigger a reminder */
X        if (NumEmitted == 0 && !Purge && !Debug) {
X           DoSubst(Banner, WorkBuf, CurDay, CurMon, CurYear, JulianToday, Msg_t);
X  	 printf("%s\n", WorkBuf);
X*** ../remind-2.0-patch1/init.c	Tue Nov  6 15:53:26 1990
X--- init.c	Tue Nov  6 15:26:23 1990
X***************
X*** 7,13 ****
X  #include "globals.h"
X  #include "protos.h"
X  
X! static char ErrMsg[] = "\n\t\tREMIND version 2.0 (C) 1990 by David Skoll.\n\nUsage: REMIND [-p | -d] [-v] [-o] [-r] filename [date]\n\n";
X  static char DPMsg[] = "Debug and Purge options conflict - Purge chosen.\n";
X  /***************************************************************/
X  /*                                                             */
X--- 7,13 ----
X  #include "globals.h"
X  #include "protos.h"
X  
X! static char ErrMsg[] = "\n\t\tREMIND version 2.1 (C) 1990 by David Skoll.\n\nUsage: REMIND [-p | -d] [-v] [-o] [-r] filename [date]\n\n";
X  static char DPMsg[] = "Debug and Purge options conflict - Purge chosen.\n";
X  /***************************************************************/
X  /*                                                             */
X*** ../remind-2.0-patch1/main.c	Tue Nov  6 15:53:34 1990
X--- main.c	Tue Nov  6 15:08:23 1990
X***************
X*** 496,514 ****
X        return tok;
X     }
X  
X!    /* Check if it's a number (optional +/- ahead of number */
X     t = temp;
X     if (isdigit(*t)) {
X        while (*++t) if (!isdigit(*t)) return tok;
X     }
X!    else if (*t == '+' || *t == '-') {
X        if (!isdigit(*++t)) return tok;
X        while (*++t) if (!isdigit(*t)) return tok;
X     }
X     else return tok;
X  
X!    /* OK, here we have a number - either a pure number, a delta or a
X!       backward look */
X  
X     if (*temp == '+') {
X        tok.type = Delta_t;
X--- 496,514 ----
X        return tok;
X     }
X  
X!    /* Check if it's a number (optional +/-/* ahead of number */
X     t = temp;
X     if (isdigit(*t)) {
X        while (*++t) if (!isdigit(*t)) return tok;
X     }
X!    else if (*t == '+' || *t == '-' || *t == '*') {
X        if (!isdigit(*++t)) return tok;
X        while (*++t) if (!isdigit(*t)) return tok;
X     }
X     else return tok;
X  
X!    /* OK, here we have a number - either a pure number, a delta, a
X!       back or a repeat marker */
X  
X     if (*temp == '+') {
X        tok.type = Delta_t;
X***************
X*** 516,521 ****
X--- 516,525 ----
X     }
X     else if (*temp == '-') {
X        tok.type = Back_t;
X+       tok.val = atoi(temp + 1);
X+    }
X+    else if (*temp == '*') {
X+       tok.type = Repeat_t;
X        tok.val = atoi(temp + 1);
X     }
X     else {
X*** ../remind-2.0-patch1/nextdate.c	Tue Nov  6 15:53:26 1990
X--- nextdate.c	Tue Nov  6 14:53:10 1990
X***************
X*** 132,142 ****
X  	 return 0;
X  
X        case 7: /* Year, month and day constrained */
X- 	 if (y > conyr || (y == conyr && m > conmon) ||
X- 	     (y == conyr && m == conmon && d > conday)) return 1;
X  	 *retday = conday;
X  	 *retmon = conmon;
X  	 *retyr = conyr;
X  	 return 0;
X  
X        case 8: /* Only the weekday constrained.  Let's go to Julian mode */
X--- 132,142 ----
X  	 return 0;
X  
X        case 7: /* Year, month and day constrained */
X  	 *retday = conday;
X  	 *retmon = conmon;
X  	 *retyr = conyr;
X+ 	 if (y > conyr || (y == conyr && m > conmon) ||
X+ 	     (y == conyr && m == conmon && d > conday)) return 1;
X  	 return 0;
X  
X        case 8: /* Only the weekday constrained.  Let's go to Julian mode */
X***************
X*** 302,312 ****
X  	 jul2 = Julian(d, m, y);
X  	 jul = Julian(conday, conmon, conyr);
X  	 while (!(wkday & (1 << (jul % 7)))) jul++;
X- 	 if (jul < jul2) return 1;
X  	 FromJulian(jul, retday, retmon, retyr);
X  	 return 0;
X     }
X  }
X- #ifndef UNIX
X- 
X- #endif UNIX
X--- 302,309 ----
X  	 jul2 = Julian(d, m, y);
X  	 jul = Julian(conday, conmon, conyr);
X  	 while (!(wkday & (1 << (jul % 7)))) jul++;
X  	 FromJulian(jul, retday, retmon, retyr);
X+ 	 if (jul < jul2) return 1;
X  	 return 0;
X     }
X  }
X*** ../remind-2.0-patch1/remind.1	Tue Nov  6 15:53:27 1990
X--- remind.1	Tue Nov  6 15:50:33 1990
X***************
X*** 134,182 ****
X  .SH THE REM COMMAND
X  The most-used command in a reminder file is the
X  .I REM
X! command.  This command is used to denote a reminder.  There are two
X  forms of the
X  .I REM
X! command; they are:
X  .RS
X! REM [ONCE]
X! [
X! .I date_spec
X! ]
X! [
X! .I delta
X! ]
X! [
X! .I back
X! ]
X! [
X! OMIT
X! .I omit_list
X! ]
X! MSG
X  .I body
X- .PP
X- REM [ONCE]
X- [
X- .I date_spec
X- ]
X- [
X- .I delta
X- ]
X- [
X- .I back
X- ]
X- [
X- OMIT
X- .I omit_list
X- ]
X- RUN
X- .I body
X  .RE
X  The
X! .I date_spec, delta
X  and
X! .I back
X  can be specified in any order.  The 
X  .I OMIT, 
X  if present, must follow these three
X--- 134,158 ----
X  .SH THE REM COMMAND
X  The most-used command in a reminder file is the
X  .I REM
X! command.  This command is used to denote a reminder.  There are many
X  forms of the
X  .I REM
X! command; they are represented by:
X! .PP
X  .RS
X! REM [ONCE] [\fIdate_spec\fR]
X! [\fIdelta\fR]
X! [\fIback\fR]
X! [\fIrepeat\fR]
X! [OMIT \fIomit_list\fR]
X! [MSG | RUN]
X  .I body
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***************
X*** 476,481 ****
X--- 452,503 ----
X  The reminder "Test3" will be triggered on the last Monday of every month,
X  as well as the three days preceding it.
X  .PP
X+ .B Repeating Reminders
X+ .PP
X+ The
X+ .I repeat
X+ component in a reminder is a number preceded by an asterisk; for example,
X+ "*14".  The
X+ .I repeat
X+ is used to remind you of events which occur regularly after a specified
X+ start date.  For example, suppose you get paid every second Thursday,
X+ and that your last payday was 8 November 1990.  The following reminder
X+ would remind you of each payday 3 days in advance:
X+ .PP
X+ .nf
X+ 	REM 8 Nov 1990 *14 +3 MSG Payday is %b!
X+ .fi
X+ .PP
X+ The
X+ .I repeat
X+ component of "*14" would cause the reminder to be triggered every 14
X+ days from the start date.
X+ .PP
X+ In order to use a
X+ .I repeat,
X+ you must fully specify the start date.  That means that if
X+ you use a
X+ .I repeat,
X+ you must specify the
X+ .I month, day
X+ and
X+ .I year.
X+ You can also specify
X+ .I weekday, back
X+ and
X+ .I local OMITs
X+ but these only affect the calculation of the start date.  Once the
X+ start date is calculated, the reminder is issued regularly every
X+ .I repeat
X+ days.  Note, in particular, that once the start date is calculated,
X+ .B remind
X+ ignores local and global
X+ .I OMITs
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***************
X*** 979,985 ****
X  The file "notes.new" would contain all non-expired lines from "notes.old."
X  All expired lines are echoed to the screen.
X  .I INCLUDEd
X! files are read an processed, but not purged.  You must purge each
X  .I INCLUDEd
X  file separately.
X  .PP
X--- 1001,1007 ----
X  The file "notes.new" would contain all non-expired lines from "notes.old."
X  All expired lines are echoed to the screen.
X  .I INCLUDEd
X! files are read and processed, but not purged.  You must purge each
X  .I INCLUDEd
X  file separately.
X  .PP
SHAR_EOF
$TOUCH -am 1106155890 patch.02 &&
chmod 0600 patch.02 ||
echo "restore of patch.02 failed"
set `wc -c patch.02`;Wc_c=$1
if test "$Wc_c" != "12130"; then
	echo original size 12130, current size $Wc_c
fi
fi
exit 0