# include	<pv.h>
# include	<ingres.h>
# include	<aux.h>
# include 	<func.h>
# include	<opsys.h>
# include	<errors.h>
#ifdef linux
# include	<time.h>
#else
extern int timezone; 
#endif

extern	short	tTdbu[];
extern	int	save();
extern	int	null_fn();

struct fn_def SaveFn =
{
	"SAVE",
	save,
	null_fn,		/* initialization function */
	null_fn,
	NULL,
	0,
	tTdbu,
	100,
	'Z',
	0
};

/*
**  SAVE RELATION UNTIL DATE
**
**	This function arranges to save a named relation until a
**	specified date.
**
**	Parameters:		(pv_type is PV_STR for all of them)
**	0 -- relation name
**	1 -- month (1 -> 12 or "jan" -> "dec" or a variety of other codes)
**	2 -- day (1 -> 31)
**	3 -- year (1970 -> ?)
**
**	Uses trace flag 44
**	Uses error messages 56xx
*/

int	DmSize[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

#ifdef linux
int dysize(int year)
{
	if (year % 400 == 0)
		return 366;
	if (year % 4 == 0 && year % 100 != 0)
		return 366;
	return 365;
}
#endif

save(parmc, parmv)
int	parmc;
PARM	parmv[];
{
	long		date;
	register int	i;
	extern DESC	Reldes;
	TID		tid;
	extern char	*Usercode;
	struct relation	relk, relt;
	int		day, month, year;

	/* convert date */
	/* "date" will be # of days from 1970 for a while */
	date = 0;

	if (parmc == 1)
		goto nodate;

	/*
	**  Validate parameters.
	**
	**	According to my pocket calculator, a 31 bit number will
	**	hold 70 years of accuracy -- hence the 2035 cutoff.  If
	**	this code is still around in 2035, I apologize in
	**	advance.
	*/

	year = atoi(parmv[3].pv_val.pv_str);
	if (year < 1970 || year > 2035)
		return (error(BADYEAR, parmv[3].pv_val.pv_str, 0));	/* bad year */
	if (monthcheck(parmv[1].pv_val.pv_str, &month))
		return (error(BADMONTH, parmv[1].pv_val.pv_str, 0));	/* bad month */
	day = atoi(parmv[2].pv_val.pv_str);
	if (day < 1 || day > monthsize(--month, year))
		return (error(BADDAY, parmv[2].pv_val.pv_str, 0));	/* bad day */

	/* do year conversion */
	for (i = 1970; i < year; i++)
	{
		date += dysize(i);
	}

	/* do month conversion */
	for (i = 0; i < month; i++)
		date += DmSize[i];
	/* once again, allow for leapyears */
	if (month >= 2 && year % 4 == 0 && year % 100 != 0)
		date += 1;

	/* do day conversion */
	date += day - 1;

	/* we now convert date to be the # of hours since 1970 */
	date *= 24;

	/* do daylight savings computations */
	/*  <<<<< none now >>>>> */

	/* convert to seconds */
	date *= 60 * 60;

	/* adjust to local time */
	date += timezone;

#	ifdef xZTR1
	if (tTf(45, 1))
		printf("%s", ctime(&date));
#	endif

nodate:
	/* let's check and see if the relation exists */
	opencatalog("relation", OR_WRITE);
	clearkeys(&Reldes);
	setkey(&Reldes, &relk, parmv[0].pv_val.pv_str, RELID);
	setkey(&Reldes, &relk, Usercode, RELOWNER);
	if (getequal(&Reldes, &relk, &relt, &tid))
	{
		return (error(RELNOTFOUND, parmv[0].pv_val.pv_str, 0));	/* relation not found */
	}

	/* check that it is not a system catalog */
	if (relt.relstat & S_CATALOG)
		return (error(NOSAVESYSREL, parmv[0].pv_val.pv_str, 0));	/* cannot save sys rel */
	/* got it; lets change the date */
	relt.relsave = date;

#	ifdef xZTR2
	if (tTf(45, 2))
	{
		printup(&Reldes, &relt);
	}
#	endif

	if ((i = replace(&Reldes, &tid, &relt, 0)) < 0)
		syserr("SAVE: replace %d", i);

	/* that's all folks.... */
	return (0);
}
/*
**  MONTHCHECK
*/

struct monthtab
{
	char	*code;
	int	month;
};

struct monthtab	Monthtab[] =
{
	"jan",		1,
	"feb",		2,
	"mar",		3,
	"apr",		4,
	"may",		5,
	"jun",		6,
	"jul",		7,
	"aug",		8,
	"sep",		9,
	"oct",		10,
	"nov",		11,
	"dec",		12,
	"january",	1,
	"february",	2,
	"march",	3,
	"april",	4,
	"june",		6,
	"july",		7,
	"august",	8,
	"september",	9,
	"october",	10,
	"november",	11,
	"december",	12,
	0
};

monthcheck(input, output)
char	*input;
int	*output;
{
	struct monthtab	*p;
	int		month;

	/* month can be an integer, or an alphanumeric code */
	month = atoi(input);
	if (month != 0)
	{
		*output = month;
		return (month < 1 || month > 12);
	}
	for (p = Monthtab; p->code; p++)
	{
		if (sequal(input, p->code))
		{
			*output = p->month;
			return (0);
		}
	}
	return (1);
}

/*
**  MONTHSIZE -- determine size of a particular month
*/

monthsize(month, year)
int	month;
int	year;
{
	register int	size;

	size = DmSize[month];
	if (month == 1 && dysize(year) == 366)
		/* This is February of a leap year */
		size++;

	return (size);

}
