[net.sources] Holidays, Easter and Date library -- Part 2 of 2

buz@ucla-cs.UUCP (04/02/87)

: 'for poor Xenix systems'
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh or : line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	datelib.c
#	easter.c
#	holidays.c
# This archive created: Wed Apr  1 14:57:44 1987
export PATH; PATH=/bin:$PATH
echo shar: extracting "'datelib.c'" '(10205 characters)'
if test -f 'datelib.c'
then
	echo shar: will not over-write existing file "'datelib.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'datelib.c'
	X
	X
	X/*            DATELIB -- LIBRARY FUNCTIONS FOR UNIX DATES         */
	X/*                                                                */
	X/*   Copyright (c) 1987 Tigertail Associates. All Rights Reserved */
	X/*                      320 North Bundy Drive                     */
	X/*                      Los Angeles, California 90049             */
	X/*                      USA                                       */
	X/*                                                                */
	X/*   e-mail: (uucp) ucla-cs!buz   or (arpa) buz@cs.ucla.edu       */
	X/*                                                                */
	X
	X#include <time.h>
	X#include "taxc.h"
	X
	X#define 	DAY		(24L*3600L)
	X#define 	YEAR	(DAY*365L)         /* in seconds */
	X#define 	RYEAR	31556926L          /* 365.2422 * DAY */
	X#define 	NERA 	(56*YEAR+14*DAY)   /* 56 years and 14 leap days */
	X
	X#ifdef BSD
	X#define     TZONE   ((TZV)*3600)       /* in seconds west of greenwich */
	Xlong time();
	Xstruct tm *localtime();
	X#else
	Xextern long timezone;
	Xextern Bool daylight;
	X#endif
	X
	X/* This library provides the following functions */
	X#if defined(lint) || defined(BSD) || defined(SYSV)
	Xlong   uxdate(), uxldate(), uxtime(), uxeaster();
	Xint    yrday(),  weeknum(), daynum();
	XBool   leap();
	Xvoid   datex(),  ldatex(),  timex();
	X#else
	Xlong   uxdate(int,int,int), uxldate(int,int,int), uxtime(int,int,int);
	Xlong   uxeaster(int);
	Xint    yrday(int,int,int), weeknum(long), daynum(long);
	XBool   leap(int);
	Xvoid   datex(long,int*,int*,int*,int*,int*);
	Xvoid   ldatex(long,int*,int*,int*,int*,int*);
	Xvoid   timex(long,int*,int*,int*);
	X#endif
	X
	X/* This external array is sometimes handy */
	Xint monthdays[] = {   0,  31,  59,  90, 120, 151, 181,
	X	                212, 243, 273, 304, 334, 365       };
	X
	X/*     Function uxdate
	X *     Return the number of seconds between Jan 1, 1970 and the 
	X *     0h 0m 0s of the date pm/pd/py in the current unix era.
	X *     The date can be viewed as Greenwich date or it can be viewed
	X *     as an abstract date, if you need to combine it with time it
	X *     needs correction for the timezone and daylight savings time.
	X *     The year is the full christian year, 70 is nonsense (and not
	X *     in the current era anyway, it is not interpreted as the year
	X *     1970.  Calculation is only done for the Gregorian calendar.
	X *
	X *     A unix date is assumed to be signed and represent dates before
	X *     1970 -- this is contrary to some speculation.  Using this scheme
	X *     unix dates cover an era from about 1903 to about 2032.  Beyond this
	X *     other reperesentations need to be used.  The alternative is to
	X *     consider unix dates as unsigned longs.  Using that scheme no date
	X *     before 1970 can be represented; these programs use signed longs
	X *     with a beginning era of 1914.
	X */
	X
	Xlong PROC uxdate ( py, pm, pd )
	Xint py, pm, pd;
	X
	X{   long yrs = (py-1970L);   /* Number of years from 0h 1970  */
	X	long nd  = yrs * 365L;   /* Number of days in those years */
	X
	X	if ( yrs >= 0 )          /* Add in bygone leap days       */
	X	then nd  += ((yrs+1L) / 4L);
	X	else nd  += ((yrs-2L) / 4L);
	X
	X    if ( pm > 2 )           /* Leap year correction for this year */
	X	then nd += leap(py);
	X
	X	     /*  ( base + prior months + this month ) * sec/day */
	X    return ( ( nd + monthdays[pm-1] + pd - 1 ) * DAY );
	X}
	X
	X    
	X
	X/*     Function uxldate
	X *     Return the number of seconds between GMT Jan 1, 1970 0h 0m 0s
	X *     and local time 0h 0m 0s of date pm/pd/py in the current era.
	X *     The date is thus based on local time. The year is the full year,
	X *     `70' is nonsense not the year `1970'.  Calculation is Gregorian
	X *     calendar for the current era.
	X */
	X
	Xlong PROC uxldate ( py, pm, pd)
	Xint py, pm, pd;
	X
	X{   long n;
	X#ifdef BSD
	X    struct tm *tp;
	X	tp = localtime();
	X	n  = uxdate ( py, pm, pd ) + (TZONE - (tp->tm_isdst ? 3600L : 0L));
	X#else
	X	tzset();
	X	n  = uxdate ( py, pm, pd ) + (timezone - (daylight ? 3600L : 0L));
	X#endif
	X    return (n);
	X}
	X
	X
	X
	X/*  Routine datex (date extraction).  The opposite function of uxdate;
	X *  that is, break down a Unix date into:
	X *     cy     current christian year            1903 .. 2036
	X *     cm     number full months so far this year  0 ..   11 where 0 = Jan
	X *     cyd    number full days   so far this year  0 ..  365 where 0 = Jan 1st
	X *     cmd    number full days   so far this month 0 ..   30 where 0 = 1st
	X *     cwd    number full days   so far this week  0 ..    6 where 0 = Sun
	X *  This provides almost the same functions as the system provided gmtime
	X *  without static storage pointers (considered dirty).
	X *  See timex for time extraction.
	X */
	X
	Xvoid PROC datex ( udate, cy, cm, cyd, cmd, cwd )
	Xlong udate;
	Xint  *cy, *cm, *cyd, *cmd, *cwd;
	X
	X{   long xd;          /* modified date -- copy to muck around with */
	X	long csy;         /* current start of year in seconds */
	X    int  nld;         /* number of leap days to start of year */
	X    long nlds;        /* number of leap days to start of year in seconds */
	X    int  xy;          /* x number of full years since 1970 */
	X	int  yd, md, wd;  /* day of year, month, and week */
	X	int  am, rm;      /* approx. month, real month */
	X	int  tld=0;       /* temporary leap day correction in days */
	X	Bool tly;         /* is leap day */
	X	int  era;         /* starting year of date sequence */
	X
	X	if ( udate < 0 )
	X	then
	X	{    era = 1914;                /* Calendar & LY orientation == 1970 */
	X		 xd  = NERA + udate; }
	X	else
	X	{    era = 1970;
	X		 xd  = udate;        }
	X
	X	nld  = (xd+YEAR+306*DAY)/(4L*YEAR+DAY); /* leap days in era incl. now */
	X	nlds = nld * DAY;
	X	xy   = (xd-nlds) / YEAR;        /* Years from origin (yrs) */
	X	*cy  = era + xy;                /* Return year */
	X
	X	csy  = xy*YEAR + ((xy+1)/4) * DAY; /* Start of this year in sec */
	X	yd   = ((xd - csy) / DAY);      /* Full days so far this year in days */
	X	/* printf ( "csy=%ld, yd=%d, cy=%d, ", csy/DAY, yd, *cy ); */
	X	if ( tly = leap(*cy) )          /* If this year a leap year */
	X	then tld = (yd>=60) ? 1 : 0;    /* Adjust for it; 2 makes Mar work */
	X	else tld = 0;
	X
	X	/* printf ( "nld=%d, xy=%d, xd=%ld, ", nld, xy, xd/DAY ); */
	X	/* printf ( "tld=%d, csy=%ld, yd=%d\n", tld, csy/DAY, yd ); */
	X
	X	*cyd = yd;	                    /* Return full days so far this year */
	X	am = (yd-tld) / 29;	            /* Approximate current month  0-12 */
	X	if ( (yd-tld) < monthdays[am] ) /* Determine real month       0-11 */
	X	then rm = am - 1;
	X	else rm = am;
	X	if (tly&&(yd==59)) then rm = 1; /* Fix leap day (Ugh) */
	X	*cm  = rm;					    /* Return full months in year so far */
	X
	X	md   = yd - monthdays[rm] - tld;/* Full days in month so far */
	X	*cmd = md;                      /* Return full days in month so far */
	X
	X	wd = ( 4L + ( xd / DAY )) % 7;  /* in days */
	X	*cwd = wd;                      /* Return full days in week so far */
	X
	X	return;
	X}
	X
	X
	X
	X/*  Routine ldatex (date extraction).  The opposite function of uxldate;
	X *  that is, break down a local time Unix date into the same things as datex.
	X */
	X
	Xvoid PROC ldatex ( udate, cy, cm, cyd, cmd, cwd )
	Xlong udate;
	Xint  *cy, *cm, *cyd, *cmd, *cwd;
	X
	X{   long ud;
	X#ifdef BSD
	X    struct tm *tp;
	X	tp = localtime();
	X	ud = udate - (TZONE - (tp->tm_isdst ? 3600L : 0L));
	X	datex( ud, cy, cm, cyd, cmd, cwd );
	X#else
	X	tzset();
	X	ud = udate - (timezone - (daylight ? 3600L : 0L));
	X	datex( ud, cy, cm, cyd, cmd, cwd );
	X#endif
	X	return;
	X}
	X
	X
	X/*     Function uxtime
	X *     Convert a broken-down local time ph:pm:ps to
	X *     seconds since local midnight.
	X */
	X
	X
	Xlong PROC uxtime ( ph, pm, ps )
	Xint ph, pm, ps;
	X
	X{   return ( ph * 3600L + pm * 60L + ps );
	X}
	X
	X
	X
	X
	X/*     Routine timex.  Do the opposite of uxtime take a Unix time
	X *     and return:
	X *         ch    number of full hours since midnight
	X *         cm    number of full minutes since last hour
	X *         cs    number of full seconds since last minute
	X */
	X
	Xvoid PROC timex ( udate, ch, cm, cs )
	Xlong udate;
	Xint *ch, *cm, *cs;
	X
	X{   long ct = (udate<0?NERA+udate:udate); /* Make date/time positive */
	X    ct     %= DAY;                        /* get rid of the days part */
	X	*ch     = ct / 3600L;                 /* get the hours out */
	X	*cm     = (int)(ct-(*ch)*3600L) / 60; /* get the minutes out */
	X	*cs     = ct % 60;                    /* get the seconds out */
	X	return;
	X}
	X
	X
	X
	X/*     Function uxeaster
	X *     Given a year (eg 1984) it provides a Unix date
	X *     for 0h Easter of that year.
	X */
	X
	X
	Xlong PROC uxeaster ( py )
	Xint py;
	X
	X{   /* The following amusing algorithm comes from page 5 of
	X     * <Practical Astronomy with your calculator>, second edition,
	X	 * by Peter Duffett-Smith, Cambridge University Press, 1979, 1981.
	X	 * The truth of the algorithm is self evident.
	X	 */
	X
	X    int  a = py % 19;
	X	int  b = py / 100;
	X	int  c = py % 100;
	X	int  d = b / 4;
	X	int  e = b % 4;
	X	int  f = (b + 8) / 25;
	X	int  g = (b - f + 1) / 3;
	X	int  h = (19*a + b - d - g + 15) % 30;
	X	int  i = c / 4;
	X	int  k = c % 4;
	X	int  l = (32 + 2*e + 2*i  - h - k) % 7;
	X	int  m = (a + 11*h + 22*l) / 451;
	X	int  t = (h + l - 7*m + 114);
	X	int  n = t / 31;
	X	int  p = t % 31;
	X
	X	return ( uxdate( py, n, p+1 ) );
	X}
	X
	X
	X/*
	X *  Function yrday
	X *  Gives the number of full days so far this year for a given date.
	X *  Returns an int.  Excludes today so Jan 1st = 0;
	X */
	X
	Xint PROC yrday ( y, m, d )
	Xint y, m, d;
	X
	X{   return ( monthdays[m-1] + (m>2?leap(y):0) + d-1);
	X         /*  days to month  +   leap day      +  month day */
	X}
	X
	X
	X
	X/*   Function leap
	X *   Return 1 if `y' is a leap year, 0 otherwise.
	X */
	X
	Xint PROC leap (y)
	Xint y;
	X
	X{   if (y % 400 == 0) then return (1);
	X    if (y % 100 == 0) then return (0);
	X    return ( ((y % 4 == 0) ? 1 : 0) );
	X}
	X
	X
	X
	X/*     Function weeknum
	X *     Return the number of full Saturdays so far this month (0-5).
	X */
	X
	Xint PROC weeknum ( udate )
	Xlong udate;
	X
	X{   int  y, m, dy, dm, dw;      /* breakdown of udate from datex */
	X
	X	datex ( udate, &y, &m, &dy, &dm, &dw );
	X    return ( (dm + (dw - dm + 35) % 7) / 7);
	X}
	X
	X
	X
	X/*     Function daynum
	X *     Return the number of full days that are the same weekday so far
	X *     this month (0-4).  e.g. If date is the 3rd Tuesday of Sept. ...
	X *     Function returns 2;
	X */
	X
	Xint PROC daynum ( udate )
	Xlong udate;
	X
	X{   int  y, m, dy, dm, dw;      /* breakdown of udate from datex */
	X
	X	datex ( udate, &y, &m, &dy, &dm, &dw );
	X    return ( dm / 7 );
	X}
SHAR_EOF
if test 10205 -ne "`wc -c < 'datelib.c'`"
then
	echo shar: error transmitting "'datelib.c'" '(should have been 10205 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'easter.c'" '(4367 characters)'
if test -f 'easter.c'
then
	echo shar: will not over-write existing file "'easter.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'easter.c'
	X
	X/*********************************************************************
	X *  
	X *                Easter Service Routine
	X *  
	X *  
	X * Program Copyright (c) 1987 Tigertail Associates.  All rights reserved.
	X *  
	X *
	X *   Synopsis:
	X *              easter [year]
	X *
	X *   If no year is specified then the date of the next Easter is printed.
	X *   If a year is specified then the date of Easter that year is printed.
	X *
	X *********************************************************************/
	X
	X#include <stdio.h>
	X#include <sys/types.h>
	X#include <time.h>
	X#include "taxc.h"
	X
	X#define DAY		(24L*3600L)
	X
	X
	X/*********************************************************************
	X *
	X *      Miscellaneous GLOBAL Values:
	X *
	X *********************************************************************/
	X
	Xchar *usage[] = { "usage: %s year",
	X                  NULLS, };
	X
	Xchar	*myname;			/* how program was invoked	*/
	X
	Xint yrday();
	Xint easter();
	X
	X/************************************************************************
	X *
	X *     main -- Calculate Date of Easter for a given year
	X *
	X ************************************************************************/
	X
	Xint PROC main (argc, argv)
	X	int	argc;
	X	char	**argv;
	X
	X{   int y, ed, mday, month;
	X	static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun" };
	X	long time(), now;
	X	char j;
	X	struct tm *localtime(), *gmtime(), *tp;
	X
	X/*********************************************************************
	X *
	X *   Get year:
	X *
	X *********************************************************************/
	X
	X	myname = *argv;
	X
	X	if (argc > 2)				/* too many args given */
	X	then Usage();
	X
	X	now = time( (long *)0 );
	X	tp  = localtime( &now );
	X	y   = tp->tm_year + 1900;
	X
	X	if ( argc == 2 )
	X	then sscanf ( argv[1], " %d%c", &y, &j );
	X
	X	if ( y < 1583 )
	X	then
	X	{    printf ( "Gregorian Easter %d is undefined.  ", y );
	X		 printf ( "Gregorian calendar did not exist.\n" );
	X		 return ( 0 );
	X		 }
	X
	X	ed = easter ( y );
	X
	X	if ( (argc < 2) && (yrday(y,ed/100,ed%100) < tp->tm_yday))
	X	then ed = easter ( ++y );
	X
	X	month = ed / 100;
	X	mday  = ed % 100;
	X	printf( "Easter %d is %s %d",  y, months[month-1], mday );
	X	if ( y < 1753 )
	X	then printf ( " Gregorian calendar\n" );
	X	else printf ( "\n" );
	X
	X
	X/*********************************************************************
	X *
	X *     Finish up:
	X *
	X *********************************************************************/
	X
	X	return (0);
	X
	X} /* main */
	X
	X
	X
	X/*********************************************************************
	X *
	X *     Procedure easter
	X * 
	X *     Given a year (eg 1984) it provides a date for Easter 422.
	X * 
	X *********************************************************************/
	X
	X
	Xint PROC easter ( py )
	Xint py;
	X
	X{   /* The following amusing algorithm comes from page 5 of
	X     * <Practical Astronomy with your calculator>, second edition,
	X	 * by Peter Duffett-Smith, Cambridge University Press, 1979, 1981.
	X	 *
	X	 * Returns: 323 for March 23.
	X	 * Returns: 402 for April 2.
	X	 */
	X
	X    int  a = py % 19;
	X	int  b = py / 100;
	X	int  c = py % 100;
	X	int  d = b / 4;
	X	int  e = b % 4;
	X	int  f = (b + 8) / 25;
	X	int  g = (b - f + 1) / 3;
	X	int  h = (19*a + b - d - g + 15) % 30;
	X	int  i = c / 4;
	X	int  k = c % 4;
	X	int  l = (32 + 2*e + 2*i  - h - k) % 7;
	X	int  m = (a + 11*h + 22*l) / 451;
	X	int  t = (h + l - 7*m + 114);
	X	int  n = t / 31;
	X	int  p = t % 31;
	X
	X	return ( n*100 + (p+1) );
	X}
	X
	X
	X
	X/************************************************************************
	X *
	X *  USAGE
	X *
	X * Print usage messages (char *usage[]) to stderr and exit nonzero.
	X * Each message is followed by a newline.
	X *
	X ************************************************************************/
	X
	XPROC Usage()
	X{
	X    register int	which = 0;		/* current line */
	X
	X	while (usage [which] != NULLS)
	X	{   fprintf (stderr, usage [which++], myname);
	X	    putc ('\n', stderr);
	X	}
	X
	X	exit (1);
	X
	X} /* Usage */
	X
	X
	X/************************************************************************
	X *
	X *   Error
	X *
	X * Print an error message to stderr and exit nonzero.  Message is preceded
	X * by "<myname>: " using global char *myname, and followed by a newline.
	X *
	X ************************************************************************/
	X
	X/* VARARGS */
	XPROC Error (message, arg1, arg2, arg3, arg4)
	X	char	*message;
	X	long	arg1, arg2, arg3, arg4;
	X
	X{   fprintf (stderr, "%s: ", myname);
	X	fprintf (stderr, message, arg1, arg2, arg3, arg4);
	X	putc ('\n', stderr);
	X
	X	exit (1);
	X
	X} /* Error */
	X
SHAR_EOF
if test 4367 -ne "`wc -c < 'easter.c'`"
then
	echo shar: error transmitting "'easter.c'" '(should have been 4367 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'holidays.c'" '(30663 characters)'
if test -f 'holidays.c'
then
	echo shar: will not over-write existing file "'holidays.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'holidays.c'
	X
	X
	X/*********************************************************************
	X *  
	X *                A Christian and Holiday Calandar Routine
	X *  
	X *  
	X * Program Copyright (c) 1987 Tigertail Associates.  All rights reserved.
	X *  
	X *
	X *   Synopsis:
	X *              holidays [flags] [ year]
	X *
	X *   For flags see usage printf below.
	X *   If no year is specified then the current year is printed.
	X *   If a year is specified then a holiday calendar for that year is printed.
	X *
	X *********************************************************************/
	X
	X#include <stdio.h>
	X#include <sys/types.h>
	X#include <time.h>
	X#include "taxc.h"
	X
	X#define DAY		        (24L*3600L)
	X#define SIDEREAL_MO		((long) (29.5306*DAY))
	X#define FIRST_Q		    ((long) ((29.5306*DAY)/4L))
	X#define FULL   		    ((long) ((29.5306*DAY)/2L))
	X#define LAST_Q 		    ((long) ((29.5306*3L*DAY)/4L))
	X#define HALF_DAY	    (DAY/2L)
	X#define D(m,w,d)	    ((m)*100+(w)*10+(d))
	X
	X
	X/*********************************************************************
	X *
	X *      Miscellaneous GLOBAL Values:
	X *
	X *********************************************************************/
	X
	Xchar *usage[] = { "usage: %s [flags] [year]",
	X                  "           Calendar Content (Default: -h)",
	X                  "      -h Holidays only printed",
	X                  "      -a All, one line for each day of year",
	X                  "      -u Print this usage statement",
	X                  "           Annotation Content (Default: -beLp1)",
	X                  "      -b Both religious and secular calendar",
	X                  "      -B Neither religious nor secular calendar",
	X                  "      -r Religious feasts",
	X                  "      -s Secular holidays and memoria",
	X                  "      -e Historical events",
	X                  "      -p <0-9> Priority limit on annotation",
	X                  "      -l Lunar phases",
	X                  "           Date Format (Default: -NwmdF)",
	X                  "      -n Day number of year",
	X                  "      -w Week day",
	X                  "      -m Month name",
	X                  "      -d Day of month",
	X                  "      -t Two digit year",
	X                  "      -f Four digit year",
	X                  "      -z todo file format",
	X                  "Capital letters reverse meaning of entry",
	X                  "If year is not specified the current year is used.",
	X                  NULLS };
	X
	Xtypedef struct { int w1, w2, w3, w4; char *desc; } hday;
	X
	X
	X/* Events in History Based on Fixed Days in a Particular Year */
	X
	X
	Xhday events[] =
	X        /*  start   end   day pri string to print */
	X        {  { 1939, 1939,   -1,  0, "Start of WW II" },           /*          */
	X		   { 1945, 1945,  132,  0, "V-E Day" },                  /* May 13th */
	X		   { 1915, 1915,  127,  0, "Sinking of the Lusitania" }, /* May  7th */
	X           { 1914, 1914,  178,  0, "Start of WW I" },            /* Jun 28th */
	X           { 1919, 1919,  178,  0, "Treaty of Versailles" },     /* Jun 28th */
	X           { 1945, 1945,  225,  0, "V-J Day" },                  /* Aug 14th */
	X           { 1929, 1929,  296,  0, "Wall Steet Panic" },         /* Oct 24th */
	X           { 1941, 1941,  325,  0, "Pearl Harbor" },             /* Nov 22nd */
	X           { 1968, 1968,  325,  0, "JFK Assassinated" },         /* Nov 22th */
	X		   {   -1,   -2,  366, 10, NULLS } };
	X
	X
	X/* Holidays in Secular Calendar Based on Fixed Days */
	X
	Xhday secular[] =
	X       /*  start   end   day pri  string to print */
	X		{ { 1896,    0,   32,  4, "Ground Hog Day" },            /* Feb  2th */
	X		  { 1896,    0,   42,  2, "Lincoln's Day (US)" },        /* Feb 12th */
	X		  { 1755,    0,   52,  2, "Washington's Day (US)" },     /* Feb 22th */
	X          {    0,    0,   90,  3, "April Fool's Day" },          /* Apr  1st */
	X          { 1890,    0,  103,  3, "Pan American Day" },          /* Apr 14th */
	X          {    0,    0,  120,  3, "May Day / Labor Day" },       /* May  1st */
	X          { 1853,/*?*/0, 124,  4, "Independence Day (Mexico)" }, /* May  5th */ 
	X          { 1819,    0,  144,  3, "National Maritime Day" },     /* May 22th */
	X          { 1880,    0,  146,  4, "British Empire Day" },        /* May 24th */
	X          { 1866, 1940,  149,  3, "Decoration Day (US)" },       /* May 30th */
	X          { 1941, 1976,  149,  3, "Memorial Day (US)" },         /* May 30th */
	X          { 1789,    0,  164,  3, "Flag Day (US)" },             /* Jun 14th */
	X          {    0,    0,  181,  4, "Canada Day" },                /* July 1th */
	X          { 1776,    0,  184,  1, "Independence Day (US)" },     /* Jul  4th */
	X          { 1778,    0,  194,  4, "Bastille Day" },              /* Jul 14th */
	X          { 1850,    0,  246,  5, "Los Angeles Day" },           /* Sep  4th */
	X          { 1854,    0,  251,  4, "California Admission Day" },  /* Sep  9th */
	X          { 1779, 1951,  256,  3, "Constitution Day (US)" },     /* Sep 14th */
	X          { 1952,    0,  259,  3, "Citizenship Day" },           /* Sep 17th */
	X          { 1940,    0,  271,  9, "Buz' Day" },                  /* Sep 29th */
	X          { 1493, 1978,  284,  2, "Columbus Day (US)" },         /* Oct 12th */
	X          { 1945,    0,  296,  2, "United Nations Day" },        /* Oct 24th */
	X          { 1920,    0,  314,  2, "Veteran's Day" },             /* Nov 11th */
	X          { 1803,    0,  308,  3, "Guy Fawkes' Day" },           /* Nov  5th */
	X          { 1941,    0,  348,  5, "Bill of Rights Day" },        /* Dec 15th */
	X          { 1903,    0,  350,  5, "Wright Bros. Day" },          /* Dec 17th */
	X          {    0,    0,  359,  5, "Boxing Day" },                /* Dec 26th */
	X		  {   -1,   -2,  366, 10, NULLS } };
	X
	X
	X
	X/* Holidays in Christian Calendar Based on Fixed Days */
	X
	Xhday  reldays[] =
	X       /*  start   end   day pri  string to print */
	X		{ {    0,    0,    5,  3, "Epiphany" },                  /* Jan  6th */
	X          {    0,    0,   32,  3, "Candelmas" },                 /* Feb  2nd */
	X          {    0,    0,   83,  4, "Mary's Annunciation" },       /* Mar 25th */
	X          {    0,    0,  179,  4, "Saint Peter's Day" },         /* Jun 29th */
	X          {    0,    0,  180,  4, "Saint Paul's Day" },          /* Jun 30th */
	X          {    0,    0,  217,  3, "Feast of the Transfiguration" },/* Aug 6th */
	X          {    0,    0,  226,  4, "Mary's Assumption" },         /* Aug 15th */
	X          {    0,    0,  250,  4, "Mary's Nativity" },           /* Sep  8th */
	X          {    0,    0,  256,  5, "Exaltation of the Cross" },   /* Sep 14th */
	X          {    0,    0,  271,  4, "Michaelmas" },                /* Sep 29th */
	X          {    0,    0,  304,  4, "All Martyr's Day" },          /* Nov  1st */
	X          {    0,    0,  330,  2, "(Advent Begins)" },           /* Nov 27th */
	X		  {   -1,   -2,  366, 10, NULLS } };
	X
	X/* Holidays in Christian Calendar based on Easter Sunday */
	X
	Xhday eastdays[] =
	X       /*  start   end   day pri  string to print */
	X        { {    0,    0,  -56,  2, "Septuagesima" }, /* 70 days before Easter? */
	X          {    0,    0,  -49,  2, "Sexagesima" },   /* 60 days before Easter? */
	X		  {    0,    0,  -50,  3, "(Carnival Begins)" },
	X          {    0,    0,  -42,  2, "Quinquagesima" },/* 50 days before Easter? */
	X          {    0,    0,  -40,  3, "Shrove Tuesday (Carnival Ends)" },
	X  /*      {    0,    0,  -40,  3, "Mardi Gras Day (Carnival Ends)" }, /* Alt  */
	X          {    0,    0,  -39,  1, "Ash Wednesday" },/* 40 days before Easter  */
	X          {    0,    0,   -7,  0, "Palm Sunday" },  /* 10 days before Easter? */
	X          {    0,    0,   -3,  2, "Maundy Thursday" },
	X          {    0,    0,   -2,  1, "Good Friday" },
	X  /*      {    0,    0,    0,  0, "Easter Sunday" },/* Handled directly in pgm*/
	X                                                    /* 40 days after Easter   */
	X          {    0,    0,   39,  3, "Holy Thursday (Feast of the Ascension)" },
	X                                                    /* 50 days after Easter   */
	X          {    0,    0,   49,  0, "Pentecost (Whitsunday)" },
	X                                                    /* 60 days after Easter?  */
	X          {    0,    0,   56,  1, "Trinity Sunday" },
	X		  {   -1,   -2,  366, 10, NULLS } };
	X
	X/* Holidays in Both Christian and Secular Calendars Based on Fixed Days */
	X
	Xhday bothdays[] =
	X       /*  start   end   day pri  string to print */
	X		{ {    0,    0,    0,  0, "New Year's Day" },            /* Jan  1st */ 
	X    /*    { 1983,   -1,   14,  2, "Martin Luther King Jr Day" }, /* Jan 15th */
	X          { 1974, 1974,    5,  0, "Daylight Savings Begins" },   /* Jan  6th */
	X          { 1942, 1942,   39,  0, "Daylight Wartime Begins" },   /* Feb  9th */
	X          {    0,    0,   44,  1, "Saint Valentines' Day" },     /* Feb 14th */
	X          { 1975, 1975,   53,  0, "Daylight Savings Begins" },   /* Feb ??th */
	X          {    0,    0,   73,  3, "Ides of March (Beware!!)" },  /* Mar 15th */
	X          {    0,    0,   75,  3, "Saint Patrick's Day" },       /* Mar 17th */
	X          {    0,    0,   79,  3, "Vernal Equinox" },            /* Mar 21st */
	X    /*    { 1914,    0,  104,  0, "Ceasar's Rendering Day" },    /* Apr 15th */
	X          {    0,    0,  171,  3, "Summer Solistice" },          /* Jun 21st */
	X          {    0,    0,  246,  5, "Kid's Day" },                 /* Sep  4th */
	X          {    0,    0,  263,  3, "Autumnal Equinox" },          /* Sep 21st */
	X          { 1942, 1942,  271,  0, "Standard Time Begins" },      /* Sep 30th */
	X          { 1918, 1919,  277,  0, "Standard Time Begins" },      /* Oct  5th */
	X          {    0,    0,  303,  0, "Halloween"},                  /* Oct 31th */
	X          {    0,    0,  354,  3, "Winter Solistice" },          /* Dec 21st */
	X          {    0,    0,  357,  0, "Christmas Eve" },             /* Dec 24th */ 
	X          {    0,    0,  358,  0, "Christmas" },                 /* Dec 25th */
	X          {    0,    0,  364,  0, "New Year's Eve" },            /* Dec 31st */
	X		  {   -1,   -2,  366, 10, NULLS } };
	X
	X
	X/* Holidays in Both Christian and Secular Calendars Based on Weekday */
	X
	Xhday daydays[] =
	X              /*    month  * 100 */
	X              /*  + wkinx  * 10  */
	X  /*  start   end + wday pri  string to print */
	X   { { 1967,    0,   10,   1, "Superbowl Sunday" },         /* 2nd Sun Jan */
	X     { 1983,    0,   21,   1, "Martin Luther King Jr Day" },/* 3rd Mon Jan */
	X  /* { 1960,    0,  250,   0, "Daylight Savings (Europe)" },/* LastSun Mar */
	X     { 1918, 1919,  250,   0, "Daylight Wartime" },         /* LastSun Mar */
	X     { 1967, 1973,  350,   0, "Daylight Savings" },         /* LastSun Apr */
	X     { 1976, 1986,  350,   0, "Daylight Savings" },         /* LastSun Apr */
	X                                                            /* 1st Sun Apr */
	X     { 1987,    0,  300,   0, "Daylight Savings (Spring Forward)" },
	X     { 1911,    0,  410,   0, "Mother's Day" },             /* 2nd Sun May */
	X     {    0,    0,  520,   0, "Father's Day" },             /* 3rd Sun Jun */
	X     { 1882,    0,  801,   0, "Labor Day" },                /* 1st Mon Sep */
	X  /* { 1960,    0,  850,   0, "Standard Time (Europe)" },   /* LastSun Sep */
	X     { 1967,    0,  950,   0, "Standard Time (Fall Back)" },/* LastSun Oct */
	X     {    0,    0, 1033,   0, "Thanksgiving Day (US)" },    /* 4th Thu Nov */
	X     {   -1,   -2, 1268,  10, NULLS } };
	X
	X
	X
	X
	X/* Holidays in Secular Calendar Based on Weekday */
	X
	Xhday dscdays[] =
	X              /*    month  * 100 */
	X              /*  + wkinx  * 10  */
	X  /*  start   end + wday pri  string to print */
	X   { { 1975,    0,  131,   1, "President's Day" },          /* 3rd Mon Feb */
	X     { 1950,    0,  426,   3, "Armed Forces' Day (US)" },   /* 3rd Sat May */
	X     { 1940, 1951,  420,   3, "I'm an American Day" },      /* 3rd Sun May */
	X     { 1977,    0,  451,   3, "Memorial Day" },             /* LastMon May */
	X     { 1865,    0,  510,   3, "Children's Day" },           /* 2nd Sun Jun */
	X     { 1979,    0,  810,   0, "Grandparent's Day" },        /* 2nd Sun Sep */
	X     { 1979,    0,  901,   2, "Child Health Day" },         /* 1st Mon Oct */
	X     { 1979,    0,  911,   2, "Columbus Day (Obs-US)" },    /* 2nd Mon Oct */
	X     { 1863,    0,  911,   4, "Thanksgiving Day (Canada)" },/* 2nd Mon Oct */
	X     {   -1,   -2, 1268,  10, NULLS } };
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	Xchar *mon_name[] ={" Jan", " Feb", " Mar", " Apr", " May", " Jun",
	X                   " Jul", " Aug", " Sep", " Oct", " Nov", " Dec" };
	Xint   mon_days[] ={  31,     28,     31,     30,     31,     30,
	X                     31,     31,     30,     31,     30,     31 };
	Xchar *day_name[] ={" Sun", " Mon", " Tue", " Wed", " Thu", " Fri", " Sat"};
	X
	X
	Xchar	*myname;			/* How program was invoked	*/
	X
	Xint  yrday();
	Xint  weeknum();
	Xint  daynum();
	Xlong uxeaster();
	Xlong uxdate();
	Xlong uxtime();
	Xvoid datex();
	X
	X
	X/************************************************************************
	X *
	X *     Holidays -- Print a holiday calendar for a given year.
	X *
	X ************************************************************************/
	X
	Xint PROC main (argc, argv)
	X	int	argc;
	X	char	**argv;
	X
	X{   int y;
	X	long time();
	X	char j;
	X	struct tm *localtime(), *gmtime(), *tp;
	X	int ds, ids, syd, ly, i, nday, wi, di, cy, cm, cyd, cmd, cwd;
	X	int ep, sp, bp, dp, rp, cp;     /* pointers into the annotation arrays */
	X	int e_month;
	X	long daysold, lbase, now, nd, cd;
	X#ifdef EBUG
	X	int  nfd;
	X	long ncd;
	X#endif
	X	Bool lwdm = FALSE;
	X	long e_s;
	X	int e_sun;
	X	char dateline[80], info[80];
	X	int mnum, mnum2;                      /* Magic numbers for checking days */
	X	int pri = 1;                          /* Priority of Holiday (important) */
	X	Bool sechf    = TRUE;				  /* Print secular holidays */
	X	Bool relhf    = TRUE;				  /* Print religious holidays */
	X	Bool eventf   = TRUE;				  /* Print history events */
	X	Bool holf;				              /* True if any holidays printed */
	X	Bool alldaysf = FALSE;                /* Print every day in year */
	X	Bool daynumf  = FALSE;                /* Print day number of day in year */
	X	Bool wdayf    = TRUE;                 /* Print week day of date */
	X	Bool monthf   = TRUE;                 /* Print month of date */
	X	Bool mdayf    = TRUE;                 /* Print month day of date */
	X	Bool syrf     = FALSE;                /* Print year in 2 digit format */
	X	Bool lyrf     = FALSE;                /* Print year in 4 digit format */
	X	Bool moif     = FALSE;                /* Print week day index in month */
	X	Bool nyrf;							  /* True if no year to be printed */
	X	Bool lunarf   = FALSE;                /* Print moon in quarter phases */
	X	Bool seasonf  = FALSE;                /* Print start of seasons */
	X	Bool todof    = FALSE;                /* Print todo file format */
	X
	X    extern	int	     optind;	          /* from getopt()	*/
	X    extern	char	*optarg;	          /* from getopt()	*/
	X    int	     option;    				  /* option "letter"	*/
	X	char *type;							  /* Religious or Holiday */
	X
	X
	X/*********************************************************************
	X *
	X *   Process Arguments
	X *
	X *********************************************************************/
	X
	X	myname = *argv;
	X
	X	optind = 1;
	X	while ((option = getopt (argc, argv, "ABCDEFHILMNRSTWZabcdefhilmnp:rstwz")) != EOF)
	X	{   switch (option)
	X	    {   case 'a':	alldaysf = TRUE;	break; /* All days printed */
	X	        case 'A':	alldaysf = FALSE;	break; /* Only Holidays printed*/
	X	        case 'b':	relhf    = TRUE;	       /* both relig & secular Hol*/
	X						eventf   = TRUE;
	X	                 	sechf    = TRUE;    break;
	X	        case 'B':	relhf    = FALSE;	       /* neither rel | secu Hol*/
	X						eventf   = FALSE;
	X	                 	sechf    = FALSE;   break;
	X	        case 'd':	mdayf    = FALSE;	break; /* Day of month */
	X	        case 'D':	mdayf    = FALSE;	break; /* Day of month deleted */
	X	        case 'e':	eventf   = TRUE;	break; /* Historical events prt */
	X	        case 'E':	eventf   = FALSE;	break; /* Historical events del */
	X	        case 'f':	lyrf     = TRUE;	break; /* Four digit year printed */
	X	        case 'F':	lyrf     = FALSE;	       /* No year printed */
	X	                 	syrf     = FALSE;   break;
	X	        case 'h':	alldaysf = FALSE;	break; /* Only holidays printed */
	X	        case 'H':	alldaysf = TRUE;	break; /* All days Printed */
	X	        case 'i':	moif     = TRUE;	break; /* Week and Day indexes */
	X	        case 'I':	moif     = FALSE;	break; /* No Week and Day indexes */
	X	        case 'l':	lunarf   = TRUE;	break; /* Phases of the moon */
	X	        case 'L':	lunarf   = FALSE;	break; /* No Phases of the moon */
	X	        case 'm':	monthf   = TRUE;	break; /* Month name printed */
	X	        case 'M':	monthf   = FALSE;	break; /* Month name deleted */
	X	        case 'n':	daynumf  = TRUE;	break; /* Day of year printed */
	X	        case 'N':	daynumf  = FALSE;	break; /* Day of year deleted */
	X	        case 'p':	pri      = atoi(optarg);	break; /* Prio of Holiday */
	X			case 'c':							   /* Christian festivals prt */
	X	        case 'r':	relhf    = TRUE;    break; /* Religious festivals prt */
	X			case 'C':							   /* Christian festivals del */
	X	        case 'R':	relhf    = FALSE;   break; /* Religious festivals del */
	X	        case 's':	sechf    = TRUE;    break; /* Secular holidays printed*/
	X	        case 'S':	sechf    = FALSE;   break; /* Secular holidays deleted*/
	X	        case 't':	syrf     = TRUE;	break; /* Two digit years */
	X	        case 'T':	lyrf     = FALSE;	       /* No year printed */
	X	                 	syrf     = FALSE;   break;
	X	        case 'w':	wdayf    = TRUE;	break; /* Week day printed */
	X	        case 'W':	wdayf    = FALSE;	break; /* Week day deleted */
	X	        case 'z':	todof    = TRUE;	break; /* Date in to do format */
	X	        case 'Z':	todof    = FALSE;	break; /* Date in to do format */
	X	        default:	Usage(); }				   /* Usage message */
	X	}
	X
	X	argc -= optind;			/* skip options	*/
	X	argv += optind;
	X
	X	now = time( (long *)0 );
	X	tp  = localtime( &now );
	X	y   = tp->tm_year + 1900;
	X
	X	if ( argc == 1 )
	X	then sscanf ( argv[0], " %d%c", &y, &j );
	X
	X	if ( y < 1913 || y > 2037 )
	X	then
	X	{    printf ( "Unix calendar out of range.  Calendar undefined.\n" );
	X		 return ( 0 ); }
	X
	X
	X
	X/*********************************************************************
	X *
	X *   Initial Setup
	X *
	X *********************************************************************/
	X
	X	cd  = uxdate   ( y, 1, 1);
	X	e_s = uxeaster ( y );  /* Get what day easter is */
	X
	X	if ( lunarf )
	X	then
	X	{   lbase  = uxdate( 1979, 2, 26 ); /* Date and time of new moon */
	X	    lbase += uxtime( 16, 0, 0 ); }
	X
	X	if (relhf && sechf)
	X	then type = "Christian and Holiday";
	X	else if ( relhf)
	X	then type = "Christian's";
	X	else type = "Holiday";
	X	e_sun = (e_s - cd)       / DAY;  /* Get what day easter is */
	X	printf ("\nA %s Calendar for Year %d\n\n", type, y);
	X
	X	ly = leap(y);
	X	if ( ly )
	X	then nd = 366;
	X	else nd = 365;
	X
	X	if (relhf || sechf || lunarf || eventf )
	X	then holf = TRUE;
	X	else holf = FALSE;
	X
	X	if ( syrf || lyrf )
	X	then nyrf = FALSE;
	X	else nyrf = TRUE;
	X
	X
	X
	X/*********************************************************************
	X *
	X *   Loop Through Days in Year
	X *
	X *********************************************************************/
	X
	X	ep = sp = bp = dp = rp = cp = 0;
	X
	X	for (nday=0; nday<nd; nday++)
	X	{   /* Get current date info out of datelib */
	X
	X		datex( cd, &cy, &cm, &cyd, &cmd, &cwd );
	X
	X#ifdef EBUG
	X	    /* Check year */
	X		if ( cy != y )
	X		then
	X		{    printf ("year check failed: y = %d, cy = %d\n", y, cy);
	X		     printf ("     cm = %d, cyd = %d, cmd = %d, cwd =%d\n",
	X			                    cm,      cyd,      cmd,     cwd); }
	X
	X	    /* Reverse Engineer the Unix date */
	X		ncd = uxdate( cy, cm+1, cmd+1 );
	X		if ( cd != ncd )
	X		then printf ("uxdate check failed: cd = %ld, ncd = %ld\n", cd, ncd);
	X
	X	    /* Reverse Engineer the Number of Full Days Sofar this Year */
	X		nfd = yrday( cy, cm+1, cmd+1 );
	X		if ( cyd != nfd || cyd != nday)
	X		then printf ("yrday check failed: nday = %d, cyd = %d, nfd = %d\n",
	X		                                       nday,      cyd,       nfd);
	X#endif
	X
	X	    wi = weeknum( cd );
	X		di = daynum ( cd );
	X
	X
	X/*********************************************************************
	X *
	X *   Format Date
	X *
	X *********************************************************************/
	X
	X		dateline[0] = NULLC;
	X		if ( todof )
	X		then /* >Sat Jun  6 87     +! */
	X			sprintf ( dateline, ">%s%s %2d %2d     +!",
	X			          day_name[cwd]+1, mon_name[cm], cmd+1, cy-1900 );
	X		else
	X		{   if ( daynumf )
	X	    	then (sprintf( info, "%3d", nday+1 ),    strcat ( dateline, info ));
	X			if ( wdayf )
	X	    	then ( strcat ( dateline, day_name[cwd] ));
	X			if ( monthf )
	X	    	then (strcat ( dateline, mon_name[cm] ));
	X			if ( mdayf )
	X	    	then (sprintf( info, " %2d", cmd+1 ),    strcat ( dateline, info ));
	X			if ( syrf )
	X	    	then (sprintf( info, " %2d ", cy-1900 ), strcat ( dateline, info ));
	X			if ( lyrf )
	X	    	then (sprintf( info, ", %4d ", cy ),     strcat ( dateline, info ));
	X			if ( nyrf )
	X	    	then  (strcat ( dateline, " " ));
	X			if ( moif )
	X	    	then (sprintf( info, "[%d-%d] ", wi,di), strcat ( dateline, info ));
	X            }
	X
	X	    if ( !lunarf ) strcat ( dateline, "  " ); 
	X
	X		if ( cyd == 0 ) /* ds is a count characters in the date string */
	X		then ids = strlen( dateline ) + (lunarf ? 5 : 0);
	X
	X		ds = ids;
	X
	X		syd = (ly&&cyd>60) ? cyd-1 : cyd; /* Create a standard date */
	X
	X		e_month = (cm == 1 && ly) ? mon_days[cm]+1 : mon_days[cm];
	X
	X		lwdm = ((cmd+9)>e_month) ? TRUE : FALSE; /* 7 + 1 for cmd + 1 to pass */
	X
	X		/* Todays magic numbers: -1 is not equal to anything else */
	X		mnum  = cm*100+di*10+cwd;               /* any other weekday */
	X		mnum2 = ( lwdm ? (cm*100+50+cwd) : -1); /* last weekday of mo */
	X
	X
	X
	X/*********************************************************************
	X *
	X *   Annotate Date with Holidays
	X *
	X *********************************************************************/
	X
	X		if ( holf )
	X		then /* Mark Holidays */
	X
	X		/* ANNOTATE WITH LUNAR AND SEASONAL EVENTS */
	X
	X		{    if ( lunarf )
	X			 then
	X	    	 {	 if ( lbase < cd )
	X			 	 then daysold =  (cd - lbase) % SIDEREAL_MO;
	X			 	 else daysold =  SIDEREAL_MO - ((lbase - cd) % SIDEREAL_MO);
	X
	X			 	 /**/ if ( (daysold > (FIRST_Q - HALF_DAY)) &&
	X				           (daysold < (FIRST_Q + HALF_DAY)) )
	X			 	 then strcat( dateline, " |)  ");
	X
	X			 	 else if ( (daysold > FULL - HALF_DAY) &&
	X				           (daysold < FULL + HALF_DAY) )
	X			 	 then strcat( dateline, " ()  ");
	X
	X			 	 else if ( (daysold > (LAST_Q - HALF_DAY)) &&
	X				           (daysold < (LAST_Q + HALF_DAY)) )
	X			 	 then strcat( dateline, " (|  ");
	X
	X			 	 else if ( (daysold > SIDEREAL_MO-HALF_DAY) ||
	X				           (daysold < HALF_DAY) )
	X			 	 then strcat( dateline, " []  ");
	X				 else strcat( dateline, "     "); }
	X
	X
	X		/* ANNOTATE WITH GENERAL INFORMATION */
	X
	X		    if ( eventf )  /* Mark Events */
	X			then
	X			{
	X				for ( ; events[ep].w1 >= 0; ep++ )
	X				{   if ( events[ep].w3 > syd )
	X					then goto secstuff;
	X				    else if ( ( events[ep].w1 <= cy  &&
	X					            events[ep].w2 >= cy  &&
	X						        events[ep].w3 == syd  ) ||
	X				              ( events[ep].w1 <= cy  &&
	X					            events[ep].w2 == 0   &&
	X						        events[ep].w3 == syd  ) ||
	X				              ( events[ep].w1 == 0   &&
	X						        events[ep].w3 == syd  ) )
	X					     then if (events[ep].w4 <= pri)
	X					          then
	X						      {    strcat( dateline, events[ep].desc );
	X			                       strcat( dateline, "  " );
	X							       goto secstuff; }
	X					}
	X
	X				}
	X
	X
	X		/* ANNOTATE WITH SECULAR INFORMATION */
	X
	X			secstuff:
	X		    if ( sechf )  /* Mark Secular Holidays */
	X			then
	X			{
	X				for ( ; secular[sp].w1 >= 0; sp++ )
	X				{   if ( secular[sp].w3 > syd )
	X					then goto wdays;
	X				    else if ( ( secular[sp].w1 == 0   &&
	X						        secular[sp].w3 == syd  ) ||
	X				              ( secular[sp].w1 <= cy  &&
	X					            secular[sp].w2 == 0   &&
	X						        secular[sp].w3 == syd  ) ||
	X				              ( secular[sp].w1 <= cy  &&
	X					            secular[sp].w2 >= cy  &&
	X						        secular[sp].w3 == syd  ) )
	X					     then if (secular[sp].w4 <= pri)
	X					          then
	X						      {    strcat( dateline, secular[sp].desc );
	X			                       strcat( dateline, "  " );
	X							       goto wdays; }
	X				}
	X
	X				wdays:
	X
	X				/* Check for Holidays Days based on Weekday */
	X
	X				for ( dp=0; dscdays[dp].w1 != -1; dp++ )
	X				if ( ( dscdays[dp].w1 == 0    &&  /* no date restrict */
	X			          (dscdays[dp].w3 == mnum ||
	X				       dscdays[dp].w3 == mnum2 )) ||
	X		             ( dscdays[dp].w1 <= cy   &&  /* no ending date   */
	X			           dscdays[dp].w2 == 0    &&
	X				      (dscdays[dp].w3 == mnum ||
	X				       dscdays[dp].w3 == mnum2 )) ||
	X		             ( dscdays[dp].w1 <= cy   &&  /* both yrs present */
	X			           dscdays[dp].w2 >= cy   &&
	X				      (dscdays[dp].w3 == mnum || 
	X				       dscdays[dp].w3 == mnum2 )))
	X			    then if (dscdays[dp].w4 <= pri)
	X			         then
	X				     {    strcat( dateline, dscdays[dp].desc );
	X	                      strcat( dateline, "  " ); }
	X
	X			/* Special Cases: Victoria Day, Easter Monday, Sadie Hawkin's Day */
	X
	X		    if ( cm == 4 && cwd == 1 && cmd<25 && cmd>18 ) /* Victoria Day */
	X		    then if ( 4 <= pri )
	X			     then strcat( dateline, "Victoria Day (Canada)  " );
	X
	X		    if ( cyd == e_sun+1 ) /* Easter Monday */
	X		    then if ( 4 <= pri )
	X			     then strcat( dateline, "Easter Monday (Canada)  " );
	X
	X		    if ( cm == 10 && cwd == 0 && cmd>11 && cmd<18 )
	X		    then if ( 4 <= pri )
	X				 then strcat( dateline, "Sadie Hawkin's Day  " );
	X
	X			}
	X
	X
	X		/* ANNOTATE WITH IMPORTANT HOLIDAYS TO BOTH CALENDARS */
	X
	X		    if ( sechf || relhf )  /* Mark Important Holidays */
	X			then
	X			{
	X				/* Check for Fixed Secular Holidays in both Calendars */
	X
	X				for ( ; bothdays[bp].w1 >= 0; bp++ )
	X				{   if ( bothdays[bp].w3 > syd )
	X					then goto bigdays;
	X				    else if ( ( bothdays[bp].w1 == 0   &&    /* no dates */
	X						        bothdays[bp].w3 == syd  ) ||
	X				              ( bothdays[bp].w1 <= cy  &&    /* no end date */
	X					            bothdays[bp].w2 == 0   &&
	X						        bothdays[bp].w3 == syd  ) ||
	X				              ( bothdays[bp].w1 <= cy  &&    /* date limits */
	X					            bothdays[bp].w2 >= cy  &&
	X						        bothdays[bp].w3 == syd  ) )
	X					then if (bothdays[bp].w4 <= pri)
	X					     then
	X						 {    strcat( dateline, bothdays[bp].desc );
	X			                  strcat( dateline, "  " );
	X							  goto bigdays; }
	X					}
	X
	X
	X				bigdays:
	X
	X				/* Check for Holidays Days based on Weekday */
	X
	X				for ( dp=0; daydays[dp].w1 != -1; dp++ )
	X				if ( ( daydays[dp].w1 == 0    &&  /* no date restrict */
	X			          (daydays[dp].w3 == mnum ||
	X				       daydays[dp].w3 == mnum2 )) ||
	X		             ( daydays[dp].w1 <= cy   &&  /* no ending date   */
	X			           daydays[dp].w2 == 0    &&
	X				      (daydays[dp].w3 == mnum ||
	X				       daydays[dp].w3 == mnum2 )) ||
	X		             ( daydays[dp].w1 <= cy   &&  /* both yrs present */
	X			           daydays[dp].w2 >= cy   &&
	X				      (daydays[dp].w3 == mnum || 
	X				       daydays[dp].w3 == mnum2 )))
	X			    then if (daydays[dp].w4 <= pri)
	X			         then
	X				     {    strcat( dateline, daydays[dp].desc );
	X	                      strcat( dateline, "  " ); }
	X
	X			/* Special_cases: Election Day and Easter */
	X
	X								   /* First Tue in Nov excep if Tue the 1st */
	X		    /**/ if ( cm == 10 && cwd == 2 && di == 0 && cmd != 0)
	X		    then strcat( dateline, "Election Day (US)  " );
	X
	X		    else if ( cm == 10 && cwd == 2 && cmd == 7) /* else Nov 8th */
	X		    then strcat( dateline, "Election Day (US)  " );
	X
	X		    if ( cyd == e_sun ) /* Easter Sunday */
	X			then strcat( dateline, "Easter Sunday  " );
	X
	X		    if ( syd == 104 ) /* April 15th */
	X		    then if ( relhf )
	X				 then strcat( dateline, "Ceasar's Rendering Day  " );
	X				 else strcat( dateline, "IRS' Day (US)  " );
	X
	X			} /* End of Secular Holidays Important to Both Calendars */
	X
	X
	X		/* ANNOTATE WITH CHRISTIAN HOLIDAYS */
	X
	X			if ( relhf )
	X			then
	X			{   for ( ; reldays[rp].w1 >= 0; rp++ )
	X				{   if ( reldays[rp].w3 > syd )
	X					then goto east;
	X				    else if ( ( reldays[rp].w1 == 0   &&
	X						        reldays[rp].w3 == syd  ) ||
	X				              ( reldays[rp].w1 <= cy  &&
	X					            reldays[rp].w2 == 0   &&
	X						        reldays[rp].w3 == syd  ) ||
	X				              ( reldays[rp].w1 <= cy  &&
	X					            reldays[rp].w2 >= cy  &&
	X						        reldays[rp].w3 == syd  ) )
	X					     then if (reldays[rp].w4 <= pri)
	X					          then
	X						      {    strcat( dateline, reldays[rp].desc );
	X			                       strcat( dateline, "  " );
	X							       goto east; }
	X					}
	X
	X		/* ANNOTATE WITH FLOATING CHRISTIAN HOLIDAYS */
	X
	X				east:
	X
	X				/* Check for Feast days based on Easter */
	X
	X				for ( ; eastdays[cp].w1 >= 0; cp++ )
	X				{   if ( eastdays[cp].w3 > (cyd - e_sun) )
	X					then goto printit;
	X				    else if ( ( eastdays[cp].w1 == 0   &&
	X						        eastdays[cp].w3 == (cyd - e_sun)  ) ||
	X				              ( eastdays[cp].w1 <= cy  &&
	X					            eastdays[cp].w2 == 0   &&
	X						        eastdays[cp].w3 == (cyd - e_sun)  ) ||
	X				              ( eastdays[cp].w1 <= cy  &&
	X					            eastdays[cp].w2 >= cy  &&
	X						        eastdays[cp].w3 == (cyd - e_sun)  ) )
	X					     then if (eastdays[cp].w4 <= pri)
	X					          then
	X						      {    strcat( dateline, eastdays[cp].desc );
	X							       goto printit; }
	X					}
	X
	X			} /* End of Christian Festivals */
	X
	X			} /* End of Holidays */
	X
	X
	X
	X
	X
	X/*********************************************************************
	X *
	X *     Print Date and Annotations if Interesting
	X *
	X *********************************************************************/
	X
	X		printit:
	X
	X		/* Trim blanks off the end of the line */
	X
	X		for ( i=strlen(dateline)-1; ((dateline[i]==' ')&&(i>0)); i-- );
	X		if (i > 0) then dateline[i+1] = NULLC;
	X
	X	    if ( alldaysf                ||           /* all days to be printed */
	X		    (strlen(dateline) > ids) ||           /* Holiday info on line */
	X			(lunarf && dateline[ids-3] != ' ') )  /* A lunar event */
	X		then printf( "%s\n", dateline );
	X
	X
	X
	X	    /* Advance yet another day */
	X		cd += DAY;
	X		}
	X
	X
	X/*********************************************************************
	X *
	X *     Finish up:
	X *
	X *********************************************************************/
	X
	X	return (0);
	X
	X} /* test of datelib */
	X
	X
	X
	X
	X
	X
	X/************************************************************************
	X *
	X *  USAGE
	X *
	X * Print usage messages (char *usage[]) to stderr and exit nonzero.
	X * Each message is followed by a newline.
	X *
	X ************************************************************************/
	X
	XPROC Usage()
	X{
	X    register int	which = 0;		/* current line */
	X
	X	while (usage [which] != NULLS)
	X	{   fprintf (stderr, usage [which++], myname);
	X	    putc ('\n', stderr);
	X	}
	X
	X	exit (1);
	X
	X} /* Usage */
SHAR_EOF
if test 30663 -ne "`wc -c < 'holidays.c'`"
then
	echo shar: error transmitting "'holidays.c'" '(should have been 30663 characters)'
fi
fi # end of overwriting check
#	End of shell archive
exit 0