[comp.sources.misc] v07i120: cal

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (08/06/89)

Posting-number: Volume 7, Issue 120
Submitted-by: vojta%math.Berkeley.EDU@ucbvax.Berkeley.EDU
Archive-name: cal

Here's a version of cal(1) which I got from comp.sources.amiga.  I've spiffed
it up to work under BSD Un*x and Turbo C, and added a man page.  Enjoy.

--Paul Vojta, vojta@math.berkeley.edu

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  cal.1 cal.c
# Wrapped by vojta@maypo on Sat Aug  5 18:02:33 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'cal.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cal.1'\"
else
echo shar: Extracting \"'cal.1'\" \(491 characters\)
sed "s/^X//" >'cal.1' <<'END_OF_FILE'
X.TH CAL 1 "5 Aug 1989" COMP.SOURCES.AMIGA
X.SH NAME
Xcal \- print calendar
X.SH SYNOPSIS
X.B cal
X[[month] year]
X.SH DESCRIPTION
X.I Cal
Xis a program which prints out a calendar either for a given month or for a
Xgiven year.  By default, it prints a calendar for the current month.  It
Xcorrectly handles the transition from the Julian to Gregorian calendars
Xin September 1752 (at least in England and colonies).
X.SH BUGS
XNote that `cal 89' refers to 89 A. D., not to 1989.
X.SH AUTHOR
XGary L. Brant
END_OF_FILE
if test 491 -ne `wc -c <'cal.1'`; then
    echo shar: \"'cal.1'\" unpacked with wrong size!
fi
# end of 'cal.1'
fi
if test -f 'cal.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cal.c'\"
else
echo shar: Extracting \"'cal.c'\" \(5158 characters\)
sed "s/^X//" >'cal.c' <<'END_OF_FILE'
X/* cal.c - print calendar for one month or one year
X *
X * cal [[month] year]
X * 
X * cal (C) 1988 by Gary L. Brant
X */
X
X#include <stdio.h>
X#include <time.h>
X#include <ctype.h>
X#include <string.h>
X#include <sys/types.h>
X
X#define	blank(addr, len)	(void) memset(addr, ' ', len)
X
X#define DPY	365L	/* days per year */
X#define FUDGE1	1	/* needed to make day of week come out right */
X#define FUDGE2	6	/* for old style (Julian) calendar */
X#define	LINEWID	71	/* width of array line[] */
X
Xint days[12] = {
X    31,  28,  31,  30,	31,  30,  31,  31,  30,  31,  30,  31
X};
Xint mdays[13] = {
X     0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334, 365
X};
Xchar *months[12] = {
X   "January ", "February ", "March ",     "April ",   "May ",      "June ",
X   "July "   , "August " , "September ", "October ", "November ", "December "
X};
Xchar monthline[] = "\t ---\t\t\t---\t\t       ---";
Xchar *monthpos[3] = {monthline+2, monthline+8, monthline+20};
Xchar dayline[] = " S  M Tu  W Th  F  S";
Xchar line[7][LINEWID];		/* line buffer */
Xint multi = 0;
X
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X   int i, k, m, y;
X   time_t t;
X   struct tm *lcl_tim;
X
X   t = time((time_t *) 0);
X   lcl_tim = localtime(&t);
X   y = lcl_tim->tm_year + 1900;
X   m = lcl_tim->tm_mon + 1;
X   if (argc == 1) {
X      fixtab (y);
X      printmonth (m, y);
X      exit (0);
X   }
X
X   if ((k = atoi (argv[1])) == 0) {
X      m = 0;
X      for (i = 0; i < 12; i++)
X	 if (cmpmonth (argv[1], months[i]) == 0) {
X	    m = i + 1;
X	    break;
X	 }
X      if (m == 0) {
X	 badarg (argv[1]);
X      }
X   }
X
X   if (argc == 2) {
X      if (k == 0) {
X	 fixtab (y);
X	 printmonth (m, y);
X      } else {
X	 multi = 1;
X	 fixtab (k);
X	 fputs("\n\n\n\t\t\t\t", stdout);
X	 putd(k);		/* put year */
X	 putchar('\n');
X	 for (m = 1; m < 13; m++)
X	    printmonth (m, k);
X	 puts("\n\n");
X      }
X      exit (0);
X   }
X
X   if (k > 0 && k < 13)
X      m = k;
X   else if (m == 0 || k != 0) {
X      badarg (argv[1]);
X   }
X
X   if (argc == 3) {
X      if ((y = atoi (argv[2])) == 0) {
X	 badarg (argv[2]);
X      }
X   }
X   fixtab (y);
X   printmonth (m, y);
X}
X
X
X/* printmonth () - either prints an entire month at a time or multiplexes
X * a month into a buffer, dumping the buffer after the third call.
X */
Xprintmonth (m, y)
Xregister int m;
Xint y;
X{
X   register int first, last;
X   register int index, p = 0;
X   register char *ll;
X   static int q = 0;
X   int l;
X
X   --m;
X   if (multi) {
X      q++;
X      if (q > 3)
X	 q = 1;
X      p = 23 * (q - 1);		/* character position of line in buffer */
X      (void) memcpy(monthpos[q-1], months[m], 3);	/* copy month name */
X      if (q == 3) {
X	 puts(monthline);
X	 for (index = 0; index < 2; ++index) {
X	    fputs(dayline, stdout);
X	    fputs("   ", stdout);
X	 }
X	 puts(dayline);
X      }
X      else
X	 blank(line[0]+p+12, 11);
X   } else {
X      q = 1;
X      fputs("   ", stdout);
X      fputs(months[m], stdout);			/* put month name */
X      putd(y);					/* put year */
X      puts(dayline);
X   }
X
X   l = 1;
X   if (p == 0) blank(line[1], 6*LINEWID);
X
X   if (y == 1752 && m == 8) {	/* special case Sep. 1752 */
X      line[1][p + 7] = '1';
X      line[1][p + 10] = '2';
X      first = 14;
X      last = 16;
X      index = 12;
X   }
X   else {
X      int dow;			/* day of week for first day of month */
X
X      first = 1;
X      dow = weekday (m, y);
X      last = 7 - dow;
X      index = 3 * dow;
X   }
X
X   for (; l < 7; ++l) {	/* loop thru month one week per line */
X      ll = line[l] + p;
X      while (first <= last) {	/* for each day in week encode day of month */
X	 if (first >= 10)
X	    ll[index] = '0' + first / 10;
X	 ll[index+1] = '0' + first % 10;
X	 index += 3;
X	 ++first;
X      }
X      if (!multi || q == 3) {
X	 index += p - 2;
X	 if (index < 0) index = 0;
X	 ll -= p;
X	 while (index >= 0 && ll[index] == ' ')
X	    --index;
X	 ll[index+1] = '\0';
X	 puts(ll);
X      }
X      last = (last + 7) > days[m] ? days[m] : last + 7;
X      index = 0;
X   }
X
X}
X
X
X/* putd - put year to standard output.
X */
Xputd (n)
Xregister int n;
X{
X   char str[5];
X   register char *p = str+4;
X
X   *p = '\0';
X   do {
X      --p;
X      *p = '0' + n % 10;
X      n = n / 10;
X   }
X   while (n);
X   puts(p);
X}
X
X
X/* fixtab - correct for leapyears.
X */
Xfixtab (y)
Xregister int y;
X{
X   register int i;
X
X   if ((y % 4) == 0) {
X      if (((y % 100) != 0) || ((y % 400) == 0) || (y < 1753)) {
X	 days[1] = 29;
X	 for (i = 2; i < 13; i++)
X	    mdays[i]++;
X      }
X   }
X}
X
X
X/* weekday - return day-of-week for first day of month.
X */
Xweekday (m, y)
Xregister int m, y;
X{
X   --y;
X   if (y > 1752-1 || (y == 1752-1 && m > 8))
X      return (mdays[m] + y + y / 4 - y / 100 + y / 400 + FUDGE1) % 7;
X   else
X      return (mdays[m] + y + y / 4		       + FUDGE2) % 7;
X}
X
X
X
Xbadarg (string)
Xchar string[];
X{
X   fputs(string, stderr);
X   fputs(" bad argument\n", stderr);
X   exit (10);
X}
X
X
X/* cmpmonth () - compare month argument entered by user with month name.
X * The comparison will be made case insensitive.
X */
Xcmpmonth (str1, str2)
Xregister char str1[], str2[];
X{
X   register int j;
X
X   if ((j = (toupper(str1[0])-str2[0])) != 0)
X      return (j);
X   else if ((j = tolower(str1[1])-str2[1]) != 0)
X      return (j);
X   else
X      return (tolower(str1[2])-str2[2]);
X}
END_OF_FILE
if test 5158 -ne `wc -c <'cal.c'`; then
    echo shar: \"'cal.c'\" unpacked with wrong size!
fi
# end of 'cal.c'
fi
echo shar: End of shell archive.
exit 0