/*
	On UNIX systems, report user, system, and total cpu time.
	On other systems, use the ANSI time.h data types to report total cpu time.
*/
#include <ncbi.h>
#include <gishlib.h>

#ifdef _SC_CLK_TCK
static long	clk_tck;
#else
#define clk_tck	CLK_TCK
#endif

static Cputime_t	time_zero;

#if defined(OS_UNIX) || defined(OS_VMS)

void
sys_times(t)
	Cputime_t PNTR t;
{
#ifdef OS_UNIX
	struct tms	tt;
#else
	struct tbuffer	tt;
#endif

	(void) times(&tt);

	if (time_zero.real == 0)
		time_zero.real = time(NULL);
	t->real = time(NULL);
#ifdef OS_UNIX
	t->user = tt.tms_utime + tt.tms_cutime;
	t->system = tt.tms_stime + tt.tms_cstime;
#else
	t->user = tt.proc_user_time;
	t->system = tt.proc_system_time;
#endif
}

void LIBCALL
sys_showtime(str, t0, t1, fp)
	CharPtr	str;
	Cputime_t PNTR t0, PNTR t1;
	FILE	*fp;
{
	char	buf[128];

	sys_strtime(buf, t0, t1);
	if (str != NULL) {
		fputs(str, fp);
		fputs(":  ", fp);
	}
	else
		fputs("CPU Time:  ", fp);

	fputs(buf, fp);
	putc('\n', fp);
}

void LIBCALL
sys_strtime(buf, t0, t1)
	CharPtr	buf;
	Cputime_t	PNTR t0, PNTR t1;
{
	long t_user, t_system, t_total;
	double	delta;
	int	days, hours, minutes, seconds;
 
#ifdef _SC_CLK_TCK
	if (clk_tck == 0)
		clk_tck = sysconf(_SC_CLK_TCK);
#endif
	if (t0 == NULL)
		t0 = &time_zero;

	t_user = t1->user - t0->user;
	t_system = t1->system - t0->system;
	t_total = t_user + t_system;

#ifdef OS_VMS
	sprintf(buf, "%ld.%02ldt",
		t_total / clk_tck,	((t_total % clk_tck) * 100) / clk_tck
		);
#else
	sprintf(buf, "%ld.%02ldu %ld.%02lds %ld.%02ldt",
		t_user / clk_tck,	((t_user % clk_tck) * 100) / clk_tck,
		t_system / clk_tck,	((t_system % clk_tck) * 100) / clk_tck,
		t_total / clk_tck,	((t_total % clk_tck) * 100) / clk_tck
		);
#endif

#if !defined(COMP_BSD) && !defined(COMP_GCC)
	delta = difftime(t1->real, t0->real);
#else
	delta = t1->real - t0->real;
#endif
	days = delta / (3600.*24.);
	if (days > 0)
		delta -= days * (3600.*24.);
	hours = delta / 3600.;
	if (hours > 0)
		delta -= hours * 3600.;
	minutes = delta / 60.;
	if (minutes > 0)
		delta -= minutes * 60.;
	seconds = MAX(delta, 0);
	strcat(buf, "  Real: ");
	buf = buf + strlen(buf);
	if (days > 0) {
		sprintf(buf, "%d days ", days);
		buf = buf + strlen(buf);
	}
	sprintf(buf, "%02d:%02d:%02d", hours, minutes, seconds);
}

#else

void
sys_times(t)
	Cputime_t	PNTR t;
{
	*t = clock();
}

void
sys_showtime(str, t0, t1, fp)
	CharPtr	str;
	Cputime_t	t0, t1;
	FILE	*fp;
{
	Cputime_t	t_total;
	int		h, m, s, hs;

#ifdef _SC_CLK_TCK
	if (clk_tck == 0)
		clk_tck = sysconf(_SC_CLK_TCK);
#endif

	t_total = t1 - t0;
	h = (t_total/clk_tck)/(60*60);
	m = ((t_total/clk_tck)%(60*60)) / 60;
	s = ((t_total/clk_tck)%(60*60)) % 60;
	hs = ((t_total%clk_tck) * 100) / clk_tck;

	if (str != NULL) {
		fputs(str, fp);
		fputs(":  ", fp);
	}
	else
		fputs("CPU Time:  ", fp);

	(void) fprintf(fp, "%02d:%02d:%02d.%02d\n", h, m, s, hs);
}
#endif /* !OS_UNIX && !OS_VMS */
