/*
 * |-----------------------------------------------------------|
 * | Copyright (c) 1991, 1990 MIPS Computer Systems, Inc.      |
 * | All Rights Reserved                                       |
 * |-----------------------------------------------------------|
 * |          Restricted Rights Legend                         |
 * | Use, duplication, or disclosure by the Government is      |
 * | subject to restrictions as set forth in                   |
 * | subparagraph (c)(1)(ii) of the Rights in Technical        |
 * | Data and Computer Software Clause of DFARS 252.227-7013.  |
 * |         MIPS Computer Systems, Inc.                       |
 * |         950 DeGuigne Avenue                               |
 * |         Sunnyvale, California 94088-3650, USA             |
 * |-----------------------------------------------------------|
 */
#ident	"$Header: cal.c,v 1.8.2.1 92/06/24 13:26:30 marker Exp $"

/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

#include <stdio.h>
#include <time.h>
char	dayw[] = {
	" S  M Tu  W Th  F  S"
};
char	*smon[]= {
	"January", "February", "March", "April",
	"May", "June", "July", "August",
	"September", "October", "November", "December",
};
char	string[432];
extern struct tm *localtime();
extern long time();
struct tm *thetime;
long timbuf;
main(argc, argv)
char *argv[];
{
	int y;
	int m;

	switch(argc) {
	case 1:
		timbuf = time(&timbuf);
		thetime = localtime(&timbuf);
		m = thetime->tm_mon + 1;
		y = thetime->tm_year + 1900;
		pmonth(m, y);
		break;
	case 2:
		y = number(argv[1]);
		if (y == -1) {
			fprintf(stderr, "cal: Invalid year %s\n", argv[1]);
			exit(2);
		}
		pyear(y);
	case 3:
		m = number(argv[1]);
		if (m == -1) {
			fprintf(stderr, "cal: Invalid month %s\n", argv[1]);
			exit(2);
		}
		y = number(argv[2]);
		if (y == -1) {
			fprintf(stderr, "cal: Invalid year %s\n", argv[2]);
			exit(2);
		}
		pmonth(m, y);
		break;
	default:
		fprintf(stderr, "usage: cal [ [month] year ]\n");
		exit(2);
	}

	exit(0);
}

/*
 *	print out just month
 */

pmonth(m, y)
	int m;
	int y;
{
	int i;

	if(m<1 || m>12) {
		fprintf(stderr, "cal: Invalid month %d\n", m);
		exit(2);
	}
	if(y<1 || y>9999) {
		fprintf(stderr, "cal: Invalid year %d\n", y);
		exit(2);
	}
	printf("   %s %u\n", smon[m-1], y);
	printf("%s\n", dayw);
	cal(m, y, string, 24);
	for(i=0; i<6*24; i+=24)
		pstr(string+i, 24);
}

/*
 *	print out complete year
 */

pyear(y)
	int y;
{
	int i;
	int j;

	if(y<1 || y>9999) {
		fprintf(stderr, "cal: Invalid year %d\n", y);
		exit(2);
	}
	printf("\n\n\n");
	printf("				%u\n", y);
	printf("\n");
	for(i=0; i<12; i+=3) {
		for(j=0; j<6*72; j++)
			string[j] = '\0';
		printf("	 %.3s", smon[i]);
		printf("			%.3s", smon[i+1]);
		printf("		       %.3s\n", smon[i+2]);
		printf("%s   %s   %s\n", dayw, dayw, dayw);
		cal(i+1, y, string, 72);
		cal(i+2, y, string+23, 72);
		cal(i+3, y, string+46, 72);
		for(j=0; j<6*72; j+=72)
			pstr(string+j, 72);
	}
	printf("\n\n\n");
	exit(0);
}

number(str)
char *str;
{
	register n, c;
	register char *s;

	n = 0;
	s = str;
	while(c = *s++) {
		if(c<'0' || c>'9') {
			return(-1);
		}
		n = n*10 + c-'0';
	}
	return(n);
}

pstr(str, n)
char *str;
{
	register i;
	register char *s;

	s = str;
	i = n;
	while(i--)
		if(*s++ == '\0')
			s[-1] = ' ';
	i = n+1;
	while(i--)
		if(*--s != ' ')
			break;
	s[1] = '\0';
	printf("%s\n", str);
}

char	mon[] = {
	0,
	31, 29, 31, 30,
	31, 30, 31, 31,
	30, 31, 30, 31,
};

cal(m, y, p, w)
char *p;
{
	register d, i;
	register char *s;

	s = p;
	d = jan1(y);
	mon[2] = 29;
	mon[9] = 30;

	switch((jan1(y+1)+7-d)%7) {

	/*
	 *	non-leap year
	 */
	case 1:
		mon[2] = 28;
		break;

	/*
	 *	1752
	 */
	default:
		mon[9] = 19;
		break;

	/*
	 *	leap year
	 */
	case 2:
		;
	}
	for(i=1; i<m; i++)
		d += mon[i];
	d %= 7;
	s += 3*d;
	for(i=1; i<=mon[m]; i++) {
		if(i==3 && mon[m]==19) {
			i += 11;
			mon[m] += 11;
		}
		if(i > 9)
			*s = i/10+'0';
		s++;
		*s++ = i%10+'0';
		s++;
		if(++d == 7) {
			d = 0;
			s = p+w;
			p = s;
		}
	}
}

/*
 *	return day of the week
 *	of jan 1 of given year
 */

jan1(yr)
{
	register y, d;

/*
 *	normal gregorian calendar
 *	one extra day per four years
 */

	y = yr;
	d = 4+y+(y+3)/4;

/*
 *	julian calendar
 *	regular gregorian
 *	less three days per 400
 */

	if(y > 1800) {
		d -= (y-1701)/100;
		d += (y-1601)/400;
	}

/*
 *	great calendar changeover instant
 */

	if(y > 1752)
		d += 3;

	return(d%7);
}
