REMIND 2.3.0 2/4

David F. Skoll dfs at doe.carleton.ca
Tue Feb 19 05:18:19 AEST 1991


#!/bin/sh
# This is part 02 of Remind 2.3.0
if touch 2>&1 | fgrep 'amc' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= files.c ==============
if test X"$1" != X"-c" -a -f 'files.c'; then
	echo "File already exists: skipping 'files.c'"
else
echo "x - extracting files.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > files.c &&
X#include <stdio.h>
X#ifndef UNIX
X#include <stdlib.h>
X#endif
X#include <string.h>
X#ifndef NO_MALLOC_H
X#include <malloc.h>
X#endif
X#ifndef UNIX
X#include <dos.h>
X#endif
X#include <fcntl.h>
X#ifdef UNIX
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <time.h>
X#endif
X#include "defines.h"
X#include "globals.h"
X#include "protos.h"
X
X#ifdef __STDC__
Xstatic int PopFile(void);
X#else
Xstatic int PopFile();
X#endif
X
X/***************************************************************/
X/*                                                             */
X/*  FILES.C                                                    */
X/*                                                             */
X/*  All the routines for opening initial file, getting         */
X/*  and settting initial file's date, closing files,           */
X/*  handling INCLUDE commands, etc.                            */
X/*                                                             */
X/***************************************************************/
X
X/* Define the structure for saving info about a file */
Xtypedef struct {
X   long offset;
X   int  curline;
X   char *name;
X} FileSave;
X
X#define MAXINCLUDE 10
X/* Set up array of MAXINCLUDE file save areas */
Xstatic FileSave stack[MAXINCLUDE];
Xstatic int      SP;
X
Xstatic FILE *fp;
X
X/***************************************************************/
X/*                                                             */
X/*  OpenFile                                                   */
X/*                                                             */
X/*  Open the named file, initialize stack, get file date.      */
X/*  If there's a problem, print an error msg and die.          */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xvoid OpenFile(char *s)
X#else
Xvoid OpenFile(s)
X     char *s;
X     
X#endif
X{
X   unsigned date, time;
X#ifndef UNIX
X   unsigned handle;
X#endif
X   int d, m, y;
X#ifndef UNIX
X   
X   /* Get the file's modification date */
X   if(_dos_open(s, O_RDONLY, &handle)) {
X      fprintf(stderr, "remind: Can't open %s.\n", s);
X      exit(1);
X#else
X   struct stat t;
X   struct tm *t1;
X      
X   /* Get the file's access date */
X   if (stat(s, &t)) {
X     fprintf(stderr, "remind: Can't find file %s.\n", s);
X     exit(1);
X#endif
X   }
X#ifndef UNIX
X   _dos_getftime(handle, &date, &time);
X   d = date & 0x1F;
X   m = (date >> 5) & 0xF;
X   y = (date >> 9) + 1980;
X#else
X   t1 = localtime(&(t.st_atime));
X#endif
X   
X#ifndef UNIX
X   if (y < BASE) LastRun = 0; else LastRun = Julian(d, m-1, y);
X   _dos_close(handle);
X#else
X   y = t1->tm_year + 1900;
X   m = t1->tm_mon;
X   d = t1->tm_mday;
X   
X   if (y < BASE) LastRun = 0; else LastRun = Julian(d, m, y);
X#endif
X   fp = fopen(s, "r");
X   if (fp == NULL) {
X      fprintf(stderr, "remind: Can't open %s.\n", s);
X      exit(1);
X   }
X   
X   CurLine = 0;
X   strcpy(FileName, s);
X   SP = 0;
X   
X   return;
X}   
X
X/***************************************************************/
X/*                                                             */
X/*  DoInclude                                                  */
X/*                                                             */
X/*  Push the state of the current file and open a new file.    */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xvoid DoInclude(char **s)
X#else
Xvoid DoInclude(s)
X     char **s;
X     
X#endif
X{
X   Token tok;
X   tok = ParseToken(s);
X   
X   /* First, check if there's room on the stack */
X   if (SP == MAXINCLUDE) {
X      Eprint("Too many levels of INCLUDE\n");
X      return;
X   }
X   
X   /* Save current data */
X#ifndef UNIX
X   stack[SP].offset = ftell(fp) - 1L;
X#else
X   stack[SP].offset = ftell(fp);
X#endif
X   stack[SP].curline = CurLine;
X   stack[SP].name = (char *) malloc(strlen(FileName)+1);
X   if (stack[SP].name == NULL) {
X      Eprint("Out of memory for INCLUDE\n");
X      return;
X   }
X   strcpy(stack[SP].name, FileName);
X   
X   SP++;
X   
X   /* Close the current file */
X   fclose(fp);
X   
X   /* Open the new file */
X   fp = fopen(tok.str, "r");
X   if (fp == NULL) {
X      Eprint("Can't open %s for INCLUDE\n", tok.str);
X      PopFile();
X      return;
X   }
X   if (Debug || Purge) {
X      Eprint("INCLUDING file %s\n", tok.str);
X   }
X   
X   /* Set the global variables */
X   CurLine = 0;
X   strcpy(FileName, tok.str);
X   return;
X}
X
X/***************************************************************/
X/*                                                             */
X/*  PopFile                                                    */
X/*                                                             */
X/*  Pop to the previous file, if there is one.  Return 0 for   */
X/*  OK, non-zero for no more files.  If we can't pop back      */
X/*  to a file, print an error message and die.                 */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xstatic int PopFile(void)
X#else
Xstatic int PopFile()
X#endif
X{
X#ifndef UNIX
X   unsigned handle, date, time;
X   struct dostime_t t;
X#endif
X
X   if (fp) fclose(fp);
X#ifndef UNIX
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	 date = CurDay;
X	 date |= (CurMon + 1) << 5;
X	 date |= (CurYear - 1980) << 9;
X	 time = t.second / 2;
X	 time |= t.minute << 5;
X	 time |= t.hour << 11;
X	 _dos_setftime(handle, date, time);
X      }
X      return 1;
X   }
X      
X#else
X   if (!SP) return -1;
X         
X#endif
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   if (fseek(fp, stack[SP].offset, SEEK_SET)) {
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   if (Debug || Purge) {
X      Eprint("Returning to file %s\n", stack[SP].name);
X   }
X   CurLine = stack[SP].curline;
X   strcpy(FileName, stack[SP].name);
X   free(stack[SP].name);
X   return 0;
X}
X/***************************************************************/
X/*                                                             */
X/*  ReadLine                                                   */
X/*                                                             */
X/*  Reads a line from the file.  If EOF, pops to previous file */
X/*  if there was one.  Returns 0 if more input, non-zero       */
X/*  if no more input.  Updates CurLine.                        */
X/*                                                             */
X/***************************************************************/
Xint ReadLine()
X{
X   int done = 0;
X   int len;
X   
X   Fresh = 1;
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         /* Remove the newline */
X         if (*Line && (*(Line + len-1)=='\n')) {
X            *(Line + strlen(Line)-1) = 0;
X            len--;
X         }
X         done = 1;
X         while(*Line && (*(Line + len-1) == '\\') && len<512) {
X 	    *(Line + len-1) = '\n';
X            if (fgets(Line+len, 512-len,fp) == NULL) {
X               *(Line + len) = 0;
X  	       break;
X	    }
X
X	    CurLine++;
X	    len = strlen(Line);
X            /* Remove the newline */
X            if (*Line && (*(Line + len-1)=='\n')) {
X               *(Line + strlen(Line)-1) = 0;
X               len--;
X            }
X         }
X      }	 
X   }
X   return 0;
X}
X
X/***************************************************************/
X/*                                                             */
X/*  TopLevel - Returns 1 if current file is top level, 0       */
X/*  if it is INCLUDEd.                                         */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xint TopLevel(void) { return (SP == 0); }
X#else
Xint TopLevel()
X{
X  return (SP == 0);
X}
X#endif
SHAR_EOF
$TOUCH -am 0218130591 files.c &&
chmod 0600 files.c ||
echo "restore of files.c failed"
set `wc -c files.c`;Wc_c=$1
if test "$Wc_c" != "8388"; then
	echo original size 8388, current size $Wc_c
fi
fi
# ============= globals.h ==============
if test X"$1" != X"-c" -a -f 'globals.h'; then
	echo "File already exists: skipping 'globals.h'"
else
echo "x - extracting globals.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > globals.h &&
X/***************************************************************/
X/*                                                             */
X/*  GLOBALS.H                                                  */
X/*                                                             */
X/*  Global variables for REMIND.                               */
X/*                                                             */
X/*  By David Skoll - 30 Sept. 1990                             */
X/*                                                             */
X/***************************************************************/
X
Xextern char *MonthName[];
Xextern char *DayName[];
Xextern Token keywd[];
Xextern int   MonthDays[];
Xextern int   MonthIndex[2][12];
Xextern int   FullOmitArray[];
Xextern int   PartOmitArray[];
Xextern char  Line[];
Xextern char  WorkBuf[];
Xextern char  TmpBuf[];
Xextern char  Fresh;
Xextern char  Purge;
Xextern char  Debug;
Xextern char  Verbose;
Xextern char  Next;
Xextern char  FileName[];
Xextern int   CurLine;
Xextern int   NumEmitted;
Xextern int   NumRem;
Xextern int   NumFullOmit;
Xextern int   NumPartOmit;
Xextern int   JulianToday;
Xextern int   LastRun;
Xextern int   CurYear;
Xextern int   CurMon;
Xextern int   CurDay;
Xextern char  Banner[];
Xextern int   RealToday;
Xextern char  IgRun;
Xextern char  IgOnce;
Xextern int   NumAtsQueued;
Xextern char  QueueAts;
Xextern char  PrintAts;
Xextern int   Calendar;
Xextern int   CalTime;
Xextern int   CalWidth;
Xextern int   SimpleCalendar;
SHAR_EOF
$TOUCH -am 0218130591 globals.h &&
chmod 0600 globals.h ||
echo "restore of globals.h failed"
set `wc -c globals.h`;Wc_c=$1
if test "$Wc_c" != "1469"; then
	echo original size 1469, current size $Wc_c
fi
fi
# ============= init.c ==============
if test X"$1" != X"-c" -a -f 'init.c'; then
	echo "File already exists: skipping 'init.c'"
else
echo "x - extracting init.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > init.c &&
X#include <stdio.h>
X#ifndef UNIX
X#include <stdlib.h>
X#endif
X#include <string.h>
X#include "defines.h"
X#include "globals.h"
X#include "protos.h"
X
X#define PATCHLEVEL 0
X
Xstatic char DPMsg[] = "Debug and Purge options conflict - Purge chosen.\n";
Xstatic char DPCMsg[] = "Calendar overrides Debug and Purge options.\n";
Xstatic char NMsg[] = "Next overrides Calendar, Debug and Purge options.\n";
X
X/***************************************************************/
X/*                                                             */
X/*  void initialize(int argc, char *argv[])                    */
X/*                                                             */
X/*  Reads command line options, sets appropriate flags         */
X/*  and FileName.  Also exits with error if invoked            */
X/*  incorrectly.                                               */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xvoid initialize(int argc, char *argv[])
X#else
Xvoid initialize(argc, argv)
X     int argc;
X     char *argv[];
X#endif
X{
X   int i;
X   char *s;
X   int d, m, y, t;
X   Token tok;
X
X   Debug    = 0;
X   Purge    = 0;
X   Verbose  = 0;
X   IgOnce   = 0;
X   IgRun    = 0;
X   Calendar = 0;
X   Next     = 0;
X   PrintAts = 1;
X   QueueAts = 1;
X   CalWidth = 10;
X   SimpleCalendar = 0;
X
X   if(argc == 1) {
X     fprintf(stderr, "\nREMIND 2.3 Patch Level %d (C) 1990, 1991 by David Skoll.\n\n", PATCHLEVEL);
X#ifdef UNIX
X     fprintf(stderr, "Usage: remind [-n | -d | -p | -c# [-w# | -s]] [-voraq] filename [date]\n\n");
X#else
X     fprintf(stderr, "Usage: remind [-n | -d | -p | -c# [-w# | -s]] [-vor] filename [date]\n\n");
X#endif
X     fprintf(stderr, "-n   Output next occurrence of reminders in simple format\n");
X     fprintf(stderr, "-d   Debug reminder file\n-p   Purge reminder file\n");
X     fprintf(stderr, "-c#  Produce calendar for # months\n");
X     fprintf(stderr, "-w#  Make calendar # columns wide\n");
X     fprintf(stderr, "-s   Produce simple calendar listing (used with -c)\n");
X     fprintf(stderr, "-v   Verbose messages\n-o   Ignore ONCE directives\n");
X     fprintf(stderr, "-r   Ignore RUN directives\n");
X#ifdef UNIX
X     fprintf(stderr, "-a   Do not trigger current AT reminders in foreground\n");
X     fprintf(stderr, "-q   Do not queue current AT reminders\n\n");
X#endif
X     exit(1);
X   }
X
X   i = 1;
X   s = argv[i];
X
X   /* Process options */
X   while (*s == '-') {
X      while (*++s) {
X         switch(upper(*s)) {
X
X	    case 'N': Next = 1;
X	             if (Calendar || Debug || Purge) {
X		        Calendar = Debug = Purge = 0;
X			fprintf(stderr, NMsg);
X	             }
X		     break;
X
X            case 'P':  Purge = 1;
X		     if (Next) {
X		        Calendar = Debug = Purge = 0;
X			fprintf(stderr, NMsg);
X		     }
X		     if (Calendar) {
X		        Debug = Purge = 0;
X			fprintf(stderr, DPCMsg);
X	             }
X                     if (Debug) {
X                        Debug = 0;
X                        fprintf(stderr, DPMsg);
X                     }
X		     break;
X
X            case 'D': Debug = 1;
X		     if (Next) {
X		        Calendar = Debug = Purge = 0;
X			fprintf(stderr, NMsg);
X		     }
X		     if (Calendar) {
X		        Debug = Purge = 0;
X			fprintf(stderr, DPCMsg);
X	             }
X	              if (Purge) {
X		         Debug = 0;
X			 fprintf(stderr, DPMsg);
X		      }
X		      break;
X
X            case 'C': Calendar = 1;
X		     if (Next) {
X		        Calendar = Debug = Purge = 0;
X			fprintf(stderr, NMsg);
X		     }
X		     if (Debug || Purge) {
X		        Debug = Purge = 0;
X			fprintf(stderr, DPCMsg);
X	             }
X                     t = atoi(s + 1);
X		     if (t > 0 && t <= 12) Calendar = t;
X                     /* Skip remaining chars on this option */
X	             while (*++s) ;
X	             s--;
X		     break;
X
X	    case 'W': CalWidth = (atoi(s+1)-9)/7;
X	             if (CalWidth < 10) CalWidth = 10;
X		     if (CalWidth > 40) CalWidth = 40;
X	             while (*++s) ;
X	             s--;
X		     break;
X
X            case 'S': SimpleCalendar = 1; break;
X
X	    case 'V': Verbose = 1; break;
X
X	    case 'O': IgOnce = 1; break;
X
X	    case 'R': IgRun = 1; break;
X#ifdef UNIX
X	    case 'A': PrintAts = 0; break;
X
X            case 'Q': QueueAts = 0; break;	      
X#endif	    
X	    default: fprintf(stderr, "Unknown option '%c' ignored.\n", *s);
X	 }			      
X      }
X      i++;
X      if (i >= argc) {
X	fprintf(stderr, "Missing filename - type 'remind' for usage information.\n");
X	 exit(1);
X      }
X      s = argv[i];
X   }	 
X   
X   /* Set FileName */
X   strcpy(FileName, argv[i++]);
X   
X   /* Get date, if supplied */
X   if (i < argc) {
X      *WorkBuf = 0;
X      while (i < argc) {
X         strcat(WorkBuf, argv[i++]);
X	 strcat(WorkBuf, " ");
X      }
X      /* Parse the date */
X      d = m = y = -1;
X      tok.type = Unknown_t;
X      s = WorkBuf;
X      while (tok.type != Eol_t) {
X         tok = ParseToken(&s);
X	 switch(tok.type) {
X
X	    case Eol_t: break;
X
X	    case Year_t: if (y == -1) 
X	                    y = tok.val;
X			 else {
X			    fprintf(stderr, "Year specified twice!\n");
X			    exit(1);
X			 }
X			 break;
X
X	    case Month_t: if (m == -1) 
X	                    m = tok.val;
X			 else {
X			    fprintf(stderr, "Month specified twice!\n");
X			    exit(1);
X			 }
X			 break;
X			 
X	    case Day_t: if (d == -1) 
X	                    d = tok.val;
X			 else {
X			    fprintf(stderr, "Day specified twice!\n");
X			    exit(1);
X			 }
X			 break;
X	   
X            default: fprintf(stderr, "Illegal token %s on command line.\n", tok.str);
X	             exit(1);
X   
X         }
X      } 
X      
X      if (d == -1 || m == -1 || y == -1) {
X         fprintf(stderr, "Date on command line must be fully specified.\n");
X	 exit(1);
X      }
X      if (CheckDate(d, m, y)) {
X         fprintf(stderr, "Illegal date on command line.\n");
X	 exit(1);
X      }
X
X      CurDay = d;
X      CurMon = m;
X      CurYear = y;
X      JulianToday = Julian(d, m, y);
X   }
X   OpenFile(FileName);
X   if (Debug) {
X      FromJulian(LastRun, &d, &m, &y);
X#ifndef UNIX
X      fprintf(stderr, "\nFile %s last modified on %s, %d %s, %d\n", FileName,
X#else
X      fprintf(stderr, "\nFile %s last accessed on %s, %d %s, %d\n", FileName,
X#endif
X                       DayName[LastRun % 7], d, MonthName[m], y);
X   }
X   return;
X}
SHAR_EOF
$TOUCH -am 0218130591 init.c &&
chmod 0600 init.c ||
echo "restore of init.c failed"
set `wc -c init.c`;Wc_c=$1
if test "$Wc_c" != "6305"; then
	echo original size 6305, current size $Wc_c
fi
fi
# ============= kall ==============
if test X"$1" != X"-c" -a -f 'kall'; then
	echo "File already exists: skipping 'kall'"
else
echo "x - extracting kall (Text)"
sed 's/^X//' << 'SHAR_EOF' > kall &&
X#!/bin/sh
X#
X# kall - kill all processes belonging to this user that match
X#           specified string.
X
Xsignal=`echo $1 | grep '^\-.*'`
Xme=`basename $0`
X
Xif [ "$signal" != "" ]; then
X	shift
Xelse
X	signal="-TERM"
Xfi
X
Xif [ "$1" = "" ]; then
X	echo "usage: $me [-signal] string [string...]"
X	echo "       kills all of your processes where command name matches"
X	echo "       any of the given strings."
X	exit
Xfi
X
Xmsg="0"
X
Xwhile [ "$1" != "" ]; do
X
X# NOTE:  You may have to modify the next line, since PS is non-portable.
X# The 'awk' command picks out the process IDs to pass them on to kill.
X	rprocs=`ps -cx | awk '{if(prog == $5) print $1}' prog=$1 -`
X	if [ "$rprocs" != "" ]; then
X		msg="1"
X		echo -n "${me}: Sending $signal signal to $1 process(es)"
X		echo '...'
X		kill $signal $rprocs
X	fi
X	shift
Xdone
X
Xif [ $msg = "1" ]; then
X    echo "${me}: Done."
Xfi
SHAR_EOF
$TOUCH -am 0218130591 kall &&
chmod 0700 kall ||
echo "restore of kall failed"
set `wc -c kall`;Wc_c=$1
if test "$Wc_c" != "852"; then
	echo original size 852, current size $Wc_c
fi
fi
# ============= main.c ==============
if test X"$1" != X"-c" -a -f 'main.c'; then
	echo "File already exists: skipping 'main.c'"
else
echo "x - extracting main.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > main.c &&
X/***************************************************************/
X/*                                                             */
X/*  REMIND - version 2.3                                       */
X/*                                                             */
X/*  By David Skoll - 11 February 1991                          */
X/*                                                             */
X/*  (C) 1990, 1991 by David Skoll - all rights reserved        */
X/*                                                             */
X/***************************************************************/
X
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X
X#ifndef UNIX
X#include <stdlib.h>
X#include <dos.h>
X#include <stdarg.h>
X#else
X#include <varargs.h>
X#include <sys/types.h>
X#ifdef SYSV
X#include <time.h>
X#else
X#include <sys/time.h>
X#endif
X#endif
X
X#include "defines.h"
X#include "protos.h"
X
X
X/* List of months */
Xchar *MonthName[] = {
X   "January", "February", "March", "April", "May", "June",
X   "July", "August", "September", "October", "November", "December"
X};
X
X/* List of weekdays */
Xchar *DayName[] = {
X   "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
X};
X
X/* List of recognized tokens - Keep them SORTED (case insensitive.) */
X
XToken keywd[] = {
X   { "AFTER",     Skip_t,    3, 3 },
X   { "April",     Month_t,  3, 3 },
X   { "AT",        At_t,      0, 2 },
X   { "August",    Month_t,  7, 3 },
X   { "BANNER",    Banner_t, 0, 3 },
X   { "BEFORE",    Skip_t,    2, 3 },
X   { "CLEAR-OMIT-CONTEXT", Clear_t, 0, 3},
X   { "December",  Month_t,  11, 3 },
X   { "February",  Month_t,  1, 3 },
X   { "Friday",    WkDay_t,  4, 3 },
X   { "INCLUDE",   Include_t, 0, 3 },
X   { "January",   Month_t,  0, 3 },
X   { "July",      Month_t,  6, 3 },
X   { "June",      Month_t,  5, 3 },
X   { "March",     Month_t,  2, 3 },
X   { "May",       Month_t,  4, 3 },
X   { "Monday",    WkDay_t,  0, 3 },
X   { "MSG",       Msg_t,    0, 3 },
X   { "November",  Month_t,  10, 3 },
X   { "October",   Month_t,  9, 3 },
X   { "OMIT",      Omit_t,   0, 3 },
X   { "ONCE",      Once_t,   0, 3 },
X   { "POP-OMIT-CONTEXT", Pop_t, 0, 3},
X   { "PUSH-OMIT-CONTEXT", Push_t, 0, 3 },
X   { "REM",       Rem_t,    0, 3 },
X   { "RUN",       Run_t,    0, 3 },
X   { "Saturday",  WkDay_t,  5, 3 },
X   { "September", Month_t,  8, 3 },
X   { "SKIP",      Skip_t,    1, 3 },
X   { "Sunday",    WkDay_t,  6, 3 },
X   { "Thursday",  WkDay_t,  3, 3 },
X   { "Tuesday",   WkDay_t,  1, 3 },
X   { "UNTIL",	  Until_t,   0, 3 },
X   { "Wednesday", WkDay_t,  2, 3 }
X};
X
X/* List of days in month - Feb MUST be 29 for CheckDate to work. */
Xint MonthDays[] = {
X   31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
X};
X
X/* Index of the first day of each month.  First array is non-leap-year;
X   second is leap-year. */
Xint MonthIndex[2][12] = {
X   { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
X   { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
X};
X
X/* Global ommissions array */
Xint FullOmitArray[FOMITSIZE];
X
X/* Global partial omissions array */
Xint PartOmitArray[POMITSIZE];
X
X/* Define the working buffers */
Xchar Line[512], WorkBuf[512];
Xchar TmpBuf[512];
Xchar Fresh;  /* True if the contents of Line are fresh */
X
X/* Global variables */
Xchar Purge, Debug, Verbose, IgRun, IgOnce, Next;
Xint LastRun;
Xchar FileName[200];
Xint CurLine;
Xchar Banner[200] = "Reminders for %w, %d%s %m, %y%o:";
Xint NumEmitted, NumRem;
Xint NumFullOmit, NumPartOmit;
Xint JulianToday, RealToday;
Xint CurYear, CurMon, CurDay;
Xchar QueueAts, PrintAts;
Xint  NumAtsQueued;
Xint Calendar, CalTime, CalWidth, SimpleCalendar;
X
Xstatic int JulFirst; /* Julian date of 1 Jan Current_year */
Xstatic int FirstYear;
X
X/***************************************************************/
X/*                                                             */
X/* Output                                                      */
X/* Output a string with line separators.                       */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xvoid Output(char *s)
X#else
Xvoid Output(s)
Xchar *s;
X#endif
X{
X   while (*s) {
X      if (*s == '\n') putchar('\\');
X      putchar(*s++);
X   }
X   putchar('\n');
X}
X
X/***************************************************************/
X/*                                                             */
X/*  int MoveBack(...)                                          */
X/*                                                             */
X/*  Move back by specified number of days, skipping holidays   */
X/*  if the amound to move back is positive; otherwise, just    */
X/*  move back (-back) days, ignoring holidays.                 */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xint MoveBack (int jul, int back, int omit)
X#else
Xint MoveBack (jul, back, omit)
X     int jul;
X     int back;
X     int omit;
X#endif
X{
X   if (back <= 0) return jul+back;
X   
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/***************************************************************/
X/*                                                             */
X/*  int ProcessLine()                                          */
X/*                                                             */
X/*  Process the line in the "Line" buffer.                     */
X/*                                                             */
X/*  Normally returns 0.  Returns 1 only if we're in Calendar   */
X/*  mode and we hit a reminder which should be placed in the   */
X/*  calendar.                                                  */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xint ProcessLine(void)
X#else
Xint ProcessLine()
X#endif
X{
X   char *s = Line;
X   Token tok;
X   int i;
X
X   while (isspace(*s)) s++;
X
X   /* Skip comments and blank lines */
X   if (*s == '#' || *s == 0) {
X      if (Purge && TopLevel()) Output(Line);
X      return 0;
X   }
X
X   tok = ParseToken(&s);
X   switch(tok.type) {
X      case Push_t:   PushOmitContext();
X      	   	     if (Purge && TopLevel()) Output(Line);
X		     break;
X
X      case Pop_t:    PopOmitContext();
X      	   	     if (Purge && TopLevel()) Output(Line);
X		     break;
X
X      case Clear_t:  ClearOmitContext();
X      	   	     if (Purge && TopLevel()) Output(Line);
X		     break;
X
X      case Banner_t: DoBanner(&s);
X		     if (Purge && TopLevel()) Output(Line);
X		     break;
X
X      case Omit_t:   i = DoGlobalOmit(&s);
X		     if (Calendar) return i;
X		     if (Purge && TopLevel())
X			if (i == -1) Eprint("Purged '%s'\n", Line);
X			else       Output(Line);
X		     break;
X
X      case Rem_t:    i = DoRem(&s);
X	             if (Calendar) return i;
X		     if (Purge && TopLevel())
X			if (i < 0) Eprint("Purged '%s'\n", Line);
X			else       Output(Line);
X		     NumRem++;
X		     break;
X
X      case Include_t: if (Purge && TopLevel()) Output(Line);
X		      DoInclude(&s);
X		      break;
X
X      default:       if (Purge && TopLevel()) Output(Line);
X		     Eprint("Unknown command '%s'\n", tok.str);
X   }
X   return 0;
X}
X
X/***************************************************************/
X/*                                                             */
X/*  Standard: void Eprint(const char *f, ...)                  */
X/*  Unix: void Eprint(va_alist)                                */
X/*                                                             */
X/*  Prints an error message.                                   */
X/*                                                             */
X/***************************************************************/
X#ifndef UNIX
Xvoid Eprint(const char *f, ...)
X#else
X/*VARARGS0*/
Xvoid Eprint(va_alist)
Xva_dcl
X#endif
X{
X#ifndef UNIX
X   va_list args;
X#else
X  va_list args;
X  char *f;
X#endif
X
X#ifndef UNIX
X   if (Verbose & Fresh) {
X#else
X  if (Verbose & Fresh) {
X#endif
X      fprintf(stderr, "\n--- %s\n", Line);
X      Fresh = 0;
X   }
X   if (Verbose) fprintf(stderr, "--- ");
X   fprintf(stderr, "%s(%d): ", FileName, CurLine);
X#ifndef UNIX
X   va_start(args, f);
X#else
X   va_start(args);
X   f = va_arg(args, char *);
X#endif
X   vfprintf(stderr, f, args);
X#ifdef UNIX
X   va_end(args);
X#endif
X}
X
X/***************************************************************/
X/*                                                             */
X/*  int DoBanner(char **s)                                     */
X/*                                                             */
X/*  Sets the "Reminders for..." banner.                        */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xint DoBanner(char **s)
X#else
Xint DoBanner(s)
X     char **s;
X#endif
X{
X   if (Purge || Next) return 0;
X   while (isspace(**s)) (*s)++;
X   strcpy(Banner, *s);
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}
X
X/***************************************************************/
X/*                                                             */
X/* int CheckDate(int d, int m, int y)                          */
X/*                                                             */
X/* Checks that a date is valid - returns 0 for OK, 1 for BAD.  */
X/*                                                             */
X/* If y=-1, just checks that month & day are valid, giving     */
X/* benefit of the doubt for February 29.                       */
X/*                                                             */
X/* No point in checking if month is valid - months are named   */
X/* and thus a month out of range can never be entered into     */
X/* the system.                                                 */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xint CheckDate(int d, int m, int y)
X#else
Xint CheckDate(d, m, y)
X     int d;
X     int m;
X     int y;
X#endif
X{
X   if (y == -1)
X      if (d > 0 && d <= MonthDays[m]) return 0; else return 1;
X   else
X      if (y < BASE || y > BASE + 85) return 1;
X      else if (d > 0 && d <= DaysInMonth(m, y)) return 0; else return 1;
X}
X
X/***************************************************************/
X/*                                                             */
X/*  int strncmpi(char *s1, char*s1, int n)                     */
X/*                                                             */
X/*  Compares first n chars of string ignoring case.            */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xint strncmpi(char *s1, char *s2, int n)
X#else
Xint strncmpi(s1, s2, n)
X     char *s1;
X     char *s2;
X     int n;
X#endif
X{
X   register int u1, u2;
X   while (n)
X   {
X      if (!*s1 || !*s2) return upper(*s1) - upper(*s2);
X      u1 = upper(*s1);
X      u2 = upper(*s2);
X      if (u1 != u2) return (u1 - u2);
X      n--;
X      s1++;
X      s2++;
X   }
X   return 0;
X}
X
X/***************************************************************/
X/*                                                             */
X/*  ParseToken(char **s);                                      */
X/*                                                             */
X/*  Parse the next token and adjust the character pointer.     */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
XToken ParseToken(char **s)
X#else
XToken ParseToken(s)
X     char **s;
X#endif
X{
X
X   Token tok;
X   char *t = TmpBuf;
X   int i, h, m;
X   int len;
X   int top, bot, mid;
X   char *colon = (char *) NULL;
X
X   *t = 0;
X   tok.str = TmpBuf;
X
X   /* Skip blank space */
X   while (isspace(**s)) (*s)++;
X
X   /* End of line ? */
X   if (**s == 0) {
X      tok.type = Eol_t;
X      tok.val = 0;
X      return tok;
X   }
X
X   /* Grab a space-delimited token */
X   while (**s != 0 && !isspace(**s)) {
X      *t++ = **s;
X      (*s)++;
X   }
X   *t = 0;
X   len = t - TmpBuf;
X
X   /* Check if it's a built-in token */
X   if (*TmpBuf >= 'A' && *TmpBuf <= 'z') {
X      top = sizeof(keywd)/sizeof(keywd[0])-1;
X      bot = 0;
X      mid = (top+bot)/2;
X      while (top >= bot && 
X              (i=strncmpi(TmpBuf, keywd[mid].str, MAX(len, (int) keywd[mid].len)))) {
X         if (i>0) bot = mid+1; else top = mid-1;
X	 mid = (top+bot)/2;
X      }
X      if (top >= bot) return keywd[mid];
X   }
X
X   tok.type = Unknown_t;
X
X   /* If it's a comment, ignore the rest of the line */
X   if (*(tok.str) == '#') {
X      tok.type = Eol_t;
X      return tok;
X   }
X
X   /* Check if it's a number (optional + / - / * ahead of number */
X   t = TmpBuf;
X   i = 1;  /* multiplication factor */
X   if (isdigit(*t)) {
X      while (*++t){
X         if (*t == ':') {
X            if (colon) return tok; else colon = t;
X         } else if (!isdigit(*t)) return tok;
X      }
X   }
X   else if (*t == '+' || *t == '-' || *t == '*') {
X      /* Check if it's a "++" or a "--" */
X      if ((*t == '+' && *(t+1) == '+') || (*t == '-' && *(t+1) == '-')) {
X         i = -1;
X         t++;
X      }
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 time,
X      back or a repeat marker */
X
X   if (colon) { /* got a time here */
X      h = atoi(TmpBuf);
X      m = atoi(colon + 1);
X      if (h >= 0 && h <= 23 && m >= 0 && m <= 59) {
X         tok.type = Time_t;
X	 tok.val = 60*h+m;
X      }
X      else return tok;
X   }
X   else if (*TmpBuf == '+') {
X      tok.type = Delta_t;
X      if (i == 1) tok.val = atoi(TmpBuf + 1);
X      else        tok.val = -atoi(TmpBuf + 2);
X   }
X   else if (*TmpBuf == '-') {
X      tok.type = Back_t;
X      if (i == 1) tok.val = atoi(TmpBuf + 1);
X      else        tok.val = -atoi(TmpBuf + 2);
X   }
X   else if (*TmpBuf == '*') {
X      tok.type = Repeat_t;
X      tok.val = atoi(TmpBuf + 1);
X   }
X   else {
X      tok.val = atoi(TmpBuf);
X      if (tok.val > 0 && tok.val <= 31) tok.type = Day_t;
X      else if (tok.val >= 100) tok.type = Year_t;
X      else {
X	 tok.type = Year_t;
X	 tok.val += 1900;
X      }
X   }
X   return tok;
X}
X
X/***************************************************************/
X/*                                                             */
X/*  int FromJulian(int jul, int *d, int *m, int *y)            */
X/*                                                             */
X/*  Convert a date from Julian to normal form.  Returns        */
X/*  0 if conversion ok, -1 otherwise.                          */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xint FromJulian(int jul, int *d, int *m, int *y)
X#else
Xint FromJulian(jul, d, m, y)
X     int jul;
X     int *d;
X     int *m;
X     int *y;
X#endif
X{
X   int t;
X
X   if (jul < 0) return -1;
X
X   if (jul >= JulFirst && JulFirst != -1) {
X      *y = FirstYear;
X      jul -= JulFirst;
X   } else *y = BASE;
X
X   *m = 0;
X
X   t = DaysInYear(*y);
X   while (jul >= t) {
X      jul -= t;
X      (*y)++;
X      t = DaysInYear(*y);
X   }
X
X   t = DaysInMonth(*m, *y);
X   while (jul >= t) {
X      jul -= t;
X      (*m)++;
X      t = DaysInMonth(*m, *y);
X   }
X   *d = jul + 1;
X   return 0;
X}
X
X/***************************************************************/
X/*                                                             */
X/*  int Julian(d, m, y)                                        */
X/*                                                             */
X/*  Converts a date to the number of days after Jan 1 1990.    */
X/*  Returns -1 if date is before Jan 1 1990.                   */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xint Julian(int d, int m, int y)
X#else
Xint Julian(d, m, y)
X     int d;
X     int m;
X     int y;
X#endif
X{
X   int iy;
X   int jul = 0;
X
X   if (y < BASE) return -1;
X   if (JulFirst == -1 || y < FirstYear)
X      for (iy = BASE; iy < y; iy++) jul += DaysInYear(iy);
X   else {
X      jul = JulFirst;
X      for (iy = FirstYear; iy < y; iy++) jul += DaysInYear(iy);
X   }
X
X   return jul + MonthIndex[IsLeapYear(y)][m] + d - 1;
X}
X
X/***************************************************************/
X/*                                                             */
X/*  int FindTodaysDate(int *d, int *m, int *y)                 */
X/*                                                             */
X/*  Obtains today's date.  Returns Julian date or -1 for       */
X/*  failure.                                                   */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xint FindTodaysDate(int *d, int *m, int *y)
X#else
Xint FindTodaysDate(d, m, y)
X     int *d;
X     int *m;
X     int *y;
X#endif
X{
X#ifndef UNIX
X   struct dosdate_t buf;
X
X   _dos_getdate(&buf);
X
X   *d = buf.day;
X   *m = buf.month - 1;
X   *y = buf.year;
X#else
X  time_t tloc;
X  struct tm *t;
X
X   (void) time(&tloc);
X   t = localtime(&tloc);
X
X   *d = t->tm_mday;
X   *m = t->tm_mon;
X   *y = t->tm_year + 1900;
X
X#endif
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#ifdef __STDC__
Xint main(int argc, char *argv[])
X#else
Xint main(argc, argv)
X     int argc;
X     char *argv[];
X#endif
X{
X#ifdef UNIX
X#ifdef SYSV
X   pid_t pid;
X#else
X   int pid;
X#endif
X#endif
X
X   NumEmitted = 0;
X   NumRem = 0;
X   JulFirst = -1;  /* Initialize JulFirst so it's not used by Julian */
X      
X   JulianToday = FindTodaysDate(&CurDay, &CurMon, &CurYear);
X   if (JulianToday < 0) {
X      fprintf(stderr, "remind: System date is illegal - Ensure that year is at least %d.\n", BASE);
X      return 1;
X   }
X   
X   RealToday = JulianToday;
X   
X   initialize(argc, argv);
X
X   FirstYear = CurYear;
X   JulFirst = Julian(1, 0, CurYear);  /* Do expensive computation once */
X   FirstYear = CurYear;
X
X   if (Calendar) {
X      DoCalendar();
X      return 0;
X   }
X   while (1) {
X      if (ReadLine()) break;
X      ProcessLine();
X   }
X/* Get rid of any spurious OMIT contexts */
X   FreeStackedOmits();
X   if (NumEmitted == 0 && NumAtsQueued == 0 && !Purge && !Debug && !Next) 
X       printf("No reminders.\n");
X#ifdef UNIX
X   if (NumEmitted == 0 && NumAtsQueued != 0 && !Purge && !Debug)
X       printf("%d reminder%s queued for later today.\n", NumAtsQueued,
X              (NumAtsQueued == 1) ? "" : "s");
X
X   fflush(stdout); /* Flush output so we don't get 2 copies when directing */
X		   /* stdout to a file. */
X
X   if (NumAtsQueued) {
X      pid = fork();
X      if (pid == -1) Eprint("Can't fork to perform ATs!\n");
X      if (pid != 0) return 0;
X      HandleQueuedAts();
X   }
X#endif
X   return 0;
X}
X/***************************************************************/
X/*                                                             */
X/* SystemTime                                                  */
X/*                                                             */
X/* Returns current system time in seconds past midnight.       */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xlong SystemTime(void)
X#else
Xlong SystemTime()
X#endif
X{
X#ifdef UNIX
X  time_t tloc;
X  struct tm *t;
X
X   (void) time(&tloc);
X   t = localtime(&tloc);
X   return (long) t->tm_hour * 3600L + (long) t->tm_min * 60L + (long) t->tm_sec;
X
X#else
X   struct dostime_t tloc;
X   _dos_gettime(&tloc);
X   return (long) tloc.hour * 3600L + (long) tloc.minute * 60L + (long) tloc.second;
X#endif
X}
SHAR_EOF
$TOUCH -am 0218130591 main.c &&
chmod 0600 main.c ||
echo "restore of main.c failed"
set `wc -c main.c`;Wc_c=$1
if test "$Wc_c" != "20411"; then
	echo original size 20411, current size $Wc_c
fi
fi
# ============= nextdate.c ==============
if test X"$1" != X"-c" -a -f 'nextdate.c'; then
	echo "File already exists: skipping 'nextdate.c'"
else
echo "x - extracting nextdate.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > nextdate.c &&
X#include "defines.h"
X#include "globals.h"
X#include "protos.h"
X
X/***************************************************************/
X/*                                                             */
X/*  int TryNextDate(int *retday, int *retmon, int *retyr,      */
X/*                  int startday, int startmon, int startyr,   */
X/*                  int conday, int conmon, int conyr,         */
X/*                  int wkday, int cons, int inc)              */
X/*                                                             */
X/*  This function tries to find the next date satisfying       */
X/*  the given constraints.  Returns                            */
X/*  0 for success.  Returns non-zero if a constraint would     */
X/*  be violated.  Note that if DAY and WEEKDAY are both        */
X/*  constrained, then MONTH and YEAR may be violated.          */
X/*  Otherwise, all constraints are honoured.                   */
X/*  The starting point for the search is thisday, etc.         */
X/*                                                             */
X/*  If inc is non-zero, then the search begins from the day    */
X/*  after the specified date.  Note that this function assumes */
X/*  that the given date is valid.                              */
X/*                                                             */
X/***************************************************************/
X#ifdef __STDC__
Xint TryNextDate(int *retday, int *retmon, int *retyr,
X		int d, int m, int y,
X		int conday, int conmon, int conyr,
X		int wkday, int cons, int inc)
X#else
Xint TryNextDate(retday, retmon, retyr, d, m, y, conday, conmon, conyr,
X                wkday, cons, inc)
X     int *retday, *retmon, *retyr, d, m, y, conday, conmon, conyr, wkday, cons, inc;
X     
X#endif
X
X{
X   int jul, jul2;
X   int dd = d, mm = m, yy = y;
X
X   if (inc)
X   {
X      d++;
X      if (d > DaysInMonth(m, y)) {
X	 m++; d = 1;
X	 if (m > 11) {
X	    y++; m = 0;
X	 }
X      }
X   }
X
X
X   switch (cons & 15) {
X
X      case 0:  /* No constraints - just use the start date */
X	 *retday = d;
X	 *retmon = m;
X	 *retyr  = y;
X	 return 0;
X
X      case 1: /* Day constrained to be d */
X	 *retday = conday;
X	 if (d > conday) {
X	    m++;
X	    if (m > 11) {y++; m=0;}
X	 }
X	 while (conday > DaysInMonth(m, y)) {
X	    m++;
X	    if (m > 11) {y++; m=0;}
X	 }
X	 *retmon = m;
X	 *retyr = y;
X	 return 0;
X
X      case 2: /* Month constrained to be m */
X	 *retmon = conmon;
X	 if (m > conmon) {y++; d = 1;}
X	 else if (m < conmon) d = 1;
X	 *retday = d;
X	 *retyr = y;
X	 return 0;
X
X      case 3: /* Month and day constrained */
X	 *retmon = conmon;
X	 *retday = conday;
X	 if (m > conmon || (m == conmon && d > conday)) y++;
X	 while (conday > DaysInMonth(conmon, y)) y++;
X	 *retyr = y;
X	 return 0;
X
X      case 4: /* Year alone constrained */
X	 if (y > conyr) return 1;
X	 *retyr = conyr;
X	 if (y < conyr) {
X	    *retmon = 0;
X	    *retday = 1;
X	 }
X	 else {
X	    *retmon = m;
X	    *retday = d;
X	 }
X	 return 0;
X
X      case 5: /* Year and day constrained */
X	 if (y > conyr) return 1;
X	 *retyr = conyr;
X	 *retday = conday;
X	 if (y < conyr) {
X	    *retmon = 0;
X	    return 0;
X	 }
X	 if (d > conday) {
X	   m++;
X	   if (m > 11) return 1;
X	 }
X	 while (conday > DaysInMonth(m, y)) {
X	    m++;
X	    if (m > 11) return 1;
X	 }
X	 *retmon = m;
X	 return 0;
X
X      case 6: /* Year and month constrained */
X	 if (y > conyr || (y == conyr && m > conmon)) return 1;
X	 *retyr = conyr;
X	 *retmon = conmon;
X	 if (y < conyr || (y == conyr && m < conmon)) {
X	    *retday = 1;
X	    return 0;
X	 }
X	 *retday = d;
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	 jul = Julian(d, m, y);
X	 while (!(wkday & (1 << (jul % 7)))) jul++;
X	 FromJulian(jul, retday, retmon, retyr);
X	 return 0;
X
X      case 9: /* GASP! day and weekday constrained .. bleah! */
X	 /* First, try last month. */
X	 jul2 = Julian(d, m, y);
X	 if (m != 0 || y != BASE)
X	 {
X	    mm--;
X	    if (mm < 0) {yy--; mm = 11;}
X
X	    /* If there are fewer days in month than required, it
X	       can't possibly match.  */
X	    if (conday <= DaysInMonth(mm, yy)) {
X	       jul = Julian(conday, mm, yy);
X	       while (!(wkday & (1 << (jul % 7)))) jul++;
X	       if (jul >= jul2) { /* SUCCESS! */
X		  FromJulian(jul, retday, retmon, retyr);
X		  return 0;
X	       }
X	    }
X	 }
X	 /* Didn't work - try this month */
X	 if (conday <= DaysInMonth(m, y)) {
X	    jul = Julian(conday, m, y);
X	    while (!(wkday & (1 << (jul % 7)))) jul++;
X	    if (jul >= jul2) { /* SUCCESS! */
X	       FromJulian(jul, retday, retmon, retyr);
X	       return 0;
X	    }
X	 }
X	 /* Argh!  Try next available month */
X	 mm = m;
X	 yy = y;
X	 do {
X	    mm++;
X	    if (mm > 11) {mm = 0; yy++;}
X	 } while (conday > DaysInMonth(mm, yy));
X	 jul = Julian(conday, mm, yy);
X	 while (!(wkday & (1 << (jul % 7)))) jul++;
X	 FromJulian(jul, retday, retmon, retyr);
X	 return 0;
X
X      case 10: /* Month and Weekday constrained */
X	 if (m < conmon) {
X	    jul = Julian(1, conmon, y);
X	    while (!(wkday & (1 << (jul % 7)))) jul++;
X	    FromJulian(jul, retday, retmon, retyr);
X	    return 0;
X	 } else if (m == conmon) {
X	    jul = Julian(d, conmon, y);
X	    while (!(wkday & (1 << (jul % 7)))) jul++;
X	    FromJulian(jul, retday, retmon, retyr);
X	    if (*retmon != conmon) {
X	       jul = Julian(1, conmon, y+1);
X	       while (!(wkday & (1 << (jul % 7)))) jul++;
X	       FromJulian(jul, retday, retmon, retyr);
X	    }
X	    return 0;
X	 } else { /* m > conmon */
X	    jul = Julian(1, conmon, y+1);
X	    while (!(wkday & (1 << (jul % 7)))) jul++;
X	    FromJulian(jul, retday, retmon, retyr);
X	    return 0;
X	 }
X
X      case 11: /* Day, Month and Weekday constrained */
X	 jul2 = Julian(d, m, y);
X
X	 /* Blip up to next valid year */
X	 while (conday > DaysInMonth(conmon, y)) y++;
X
X	 /* Try this year */
X	 jul = Julian(conday, conmon, y);
X	 while (!(wkday & (1 << (jul % 7)))) jul++;
X	 if (jul >= jul2) {
X	    FromJulian(jul, retday, retmon, retyr);
X	    return 0;
X	 }
X
X	 /* Must be next year */
X	 jul = Julian(conday, conmon, y+1);
X	 while (!(wkday & (1 << (jul % 7)))) jul++;
X	 FromJulian(jul, retday, retmon, retyr);
X	 return 0;
X
X      case 12: /* Weekday and year specified */
X	 if (y > conyr) return 1;
X	 if (y == conyr) {mm = m; dd = d;} else {mm = 0; dd = 1;}
X	 jul = Julian(dd, mm, conyr);
X	 while (!(wkday & (1 << (jul % 7)))) jul++;
X	 FromJulian(jul, retday, retmon, retyr);
X	 if (*retyr == conyr) return 0; else return 1;
X
X      case 13: /* Weekday, year and day specified */
X	 if (y > conyr+1 || (y > conyr && m>0)) return 1;
X	 jul2 = Julian(d, m, y);
X	 if (y > conyr ) {
X	    jul = Julian(conday, 11, conyr);
X	    while (!(wkday & (1 << (jul % 7)))) jul++;
X	    if (jul >= jul2) {
X	       FromJulian(jul, retday, retmon, retyr);
X	       return 0;
X	    }
X	 } else if (y < conyr) {
X	    jul = Julian(conday, 0, conyr);
X	    while (!(wkday & (1 << (jul % 7)))) jul++;
X	    FromJulian(jul, retday, retmon, retyr);
X	    return 0;
X	 }
X	 else {
X	    /* Try last month */
X	    if (m > 0) {
X	       mm = m - 1;
X	       while (conday > DaysInMonth(mm, y)) mm--;
X	       jul = Julian(conday, mm, y);
X	       while (!(wkday & (1 << (jul % 7)))) jul++;
X	       if (jul >= jul2) {
X		  FromJulian(jul, retday, retmon, retyr);
X		  return 0;
X	       }
X	    }
X	    /* Try this month */
X	    if (conday <= DaysInMonth(m,y)) {
X	       jul = Julian(conday, m, y);
X	       while (!(wkday & (1 << (jul % 7)))) jul++;
X	       if (jul >= jul2) {
X		  FromJulian(jul, retday, retmon, retyr);
X		  return 0;
X	       }
X	    }
X	    /* Try next month */
X	    if (m == 11) return 1;
X	    m++;
X	    while (conday > DaysInMonth(m, y)) m++;
X	    jul = Julian(conday, m, y);
X	    while (!(wkday & (1 << (jul % 7)))) jul++;
X	    FromJulian(jul, retday, retmon, retyr);
X	    return 0;
X	 }
X
X      case 14:  /* Weekday, Month and Year specified */
X	 if (y > conyr || (y == conyr && m > conmon)) return 1;
X	 if (conyr > y || (conyr == y && conmon > m)) {
X	    jul = Julian(1, conmon, conyr);
X	    while (!(wkday & (1 << (jul % 7)))) jul++;
X	    FromJulian(jul, retday, retmon, retyr);
X	    if (*retmon == conmon) return 0; else return 1;
X	 } else {
X	    jul = Julian(d, m, y);
X	    while (!(wkday & (1 << (jul % 7)))) jul++;
X	    FromJulian(jul, retday, retmon, retyr);
X	    if (*retmon == conmon) return 0; else return 1;
X
X	 }
X
X      case 15: /* Weekday, day, month and year specified */
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}
SHAR_EOF
$TOUCH -am 0218130591 nextdate.c &&
chmod 0600 nextdate.c ||
echo "restore of nextdate.c failed"
set `wc -c nextdate.c`;Wc_c=$1
if test "$Wc_c" != "8719"; then
	echo original size 8719, current size $Wc_c
fi
fi
echo "End of part 2, continue with part 3"
exit 0



More information about the Alt.sources mailing list