/*
 * getmisc.c -- various functions, mostly used by getyacc.y 
 */

#include <stdio.h>

#include "jul_greg.h"

extern struct jul_greg jg;

#define LEAP(x)	((((jg.y % 4) == 0) && ((jg.y % 100) != 0)) || ((jg.y % 400) == 0))

int
jg_check()
{
	/* ok, ok... so every year's a leap year.... Sadie Hawkins, yet! */
	static int      days_month[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

	if (jg.m < 1 || jg.m > 12 ||
	    jg.d < 1 || jg.d > days_month[jg.m - 1] ||
	    (jg.m == 2 && jg.d > 28 && !LEAP(jg.y)) ||
	    jg.wd < 0 || jg.wd > 6
		) {
		fprintf(stderr, "jg_check: month, day, or weekday out of range\n");
		return 1;
	} else {
		if (jg.y < 1583)
			fprintf(stderr, "warning: %d is before the Gregorian calendar -- calculations incorrect\n", jg.y);
		return 0;
	}
}

int
jg_update(num, unit)
	int             num, unit;
{
	int             delta;

	delta = 0;
	switch (unit) {
	case 'w':
		num *= 7;
	case 'd':
		delta = num;
		break;
	case 'm':	/* allow month adjustments to go outside  year */
		jg.m += num - 1;
		jg.y += jg.m / 12;
		if ((jg.m %= 12) < 0) {
			jg.y--;
			jg.m += 12;
		}
		jg.m++;
		break;
	case 'y':
		jg.y += num;
		break;
	default:
		break;
	}
	if (jg_check())
		return 1;

	jday(&jg);		/* calculate julian day from possibly
					modified gregorian date in jg */
	jg.j += delta;		/* add in the date changes, if any */
	jdate(&jg);		/* recalculate the gregorian date from
					corrected julian day */
	return 0;
}

int
jg_nth_day(num, day)
	int             num, day;
{
	int             delta;

	jg.d = 1;
	jg_update(0, 0);
	delta = day - jg.wd;
	delta = delta < 0 ? delta + num * 7 : delta + (num - 1) * 7;
	jg.d = 1 + delta;
	return jg_update(0, 0);
}

#include <time.h>

int
jg_init(date)
	struct jul_greg *date;
{
	struct tm      *tm;
	long            clock;
	long            time();

	time(&clock);
	tm = localtime(&clock);

	date->m = tm->tm_mon + 1;
	date->d = tm->tm_mday;
	date->y = tm->tm_year + 1900;
	jday(date);		/* first set julian day */
	jdate(date);		/* so can then set weekday */
	return jg_check();
}

int
jg_jdate(j)
	long            j;
{
	jg.j = j;
	jdate(&jg);
	return 0;
}
