# include	<pv.h>
# include	<ingres.h>
# include	<aux.h>
# include 	<func.h>
# include	<opsys.h>
# ifndef bsd386          /*  by  K.Okamoto   */
# ifdef xV7_UNIX
# include	<sys/timeb.h>
# endif xV7_UNIX
# endif bsd386
# include	<sccs.h>
# include	<errors.h>

SCCSID(@(#)save.c	8.4	1/22/88)

extern	short	tTdbu[];
extern	int	save();
extern	void	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};

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;
# ifndef bsd386                          /*  by   K.Okamoto   */
# ifdef xV7_UNIX
	struct timeb	timeb;
# else xV7_UNIX
	extern int	timezone;	/* defined by ctime(3) */
# endif xV7_UNIX
# else bsd386                           /*  by   K.Okamoto     */
	extern int	timezone;	/* defined by ctime(3) */
# endif
/*	extern int	dysize();	 ditto */ 

	/* 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 */
# ifndef bsd386                        /*  by   K.Okamoto   */
# if defined(xV7_UNIX)
	ftime(&timeb);
	date += ((long) timeb.timezone) * 60;
# else xV7_UNIX
	date += timezone;
# endif xV7_UNIX
# else bsd386                         /*   by  K.Okamoto   */
	date += timezone;
# endif

#	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;
{
	register 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;
	extern int	dysize();	/* defined in ctime */

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

	return (size);

}

dysize(year)
int year;
{
  int days=365;
  if (year % 4 == 0 && year % 100 != 0)
    days=366;
  return(days);
}
