asctime.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	char *asctime(const struct tm *timeptr)
 *
 *	converts the broken-down time in the structure pointed to by
 *	timeptr into a string in the form 
 *
 *		Sat Jul 16 02:13:36 1988\n\0
 *
 *	returns a pointer to the string.
 */

#include <stdio.h>
#include <time.h>

char *
asctime(const struct tm *timeptr)
{
	static char days[7][4] = {
		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
	};
	static char months[12][4] = {
		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
	};
	static char buffer[26];

	sprintf(buffer, "%s %s %2d %02d:%02d:%02d %4d\n",
			days[timeptr->tm_wday], months[timeptr->tm_mon],
			timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min,
			timeptr->tm_sec, timeptr->tm_year+1900);
	return(buffer);
}

clock.c
/* Copyright 1988 Manx Software Systems, Inc. */

/*
 *	clock_t clock(void);
 *
 *	determines the processor time used.
 *
 *	returns the implementation's best approximation to the processor time
 *	used by the program since the beginning of an implementation-defined
 *	era related only to the program invocation. To determine the time in
 *	seconds, the value returned by the clock function should be divided
 *	by the value of the macro CLK_TCK. If the processor time used is not
 *	available or its value cannot be represented, the function returns
 *	the value (clock_t)-1.
 */

#include <time.h>

clock_t
clock(void)
{
	return((clock_t)-1);
}

ctime.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	char *ctime(const time_t *timer);
 *
 *	converts the calendar time pointed to by timer to local time in the
 *	form of a string.
 *
 *	returns the pointer returned by the asctime function with that
 *	broken-down time as argument.
 */

#include <time.h>

char *ctime(const time_t *timer)
{
	return(asctime(localtime(timer)));
}

difftime.c
/* Copyright 1988 Manx Software Systems, Inc. */

/*
 *	double difftime(time_t time1, time_t, time0);
 *
 *	computes the difference between two calendar times: time1 - time0.
 *
 *	returns the difference expressed in seconds as a double.
 */

#include <time.h>

double difftime(time_t time1,time_t time0)
{
   return((double)(time1 -time0));
}

gmtime.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	struct tm *gmtime(const time_t *timer)
 *
 *	converts the calendar time pointed to by timer into a broken-down
 *	time, expressed as Coordinated Universal Time (UTC).
 *
 *	returns a pointer to that object, or a null pointer if UTC is not
 *	available.
 */

#include <stdlib.h>
#include <time.h>

#define SECS_IN_HOUR (60 * 60L)

struct tm *gmtime(const time_t *timer)
{
	struct tm *localtime();
	char *getenv();
	register char *name;
	int tz;
    time_t temp;


    if ((name = getenv("TZ")) == 0)
	  return((struct tm *) 0);
	tz = atoi(name+3);
	temp = *timer + tz * SECS_IN_HOUR;
	return(localtime(&temp));
}

localtime.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/* 
 *	struct tm *localtime(const time_t *clock)
 *
 *	converts the calendar time pointed to by timer into broken-down
 *	time, expressed as local time.
 *
 *	returns a pointer to that object.
 */

#include <time.h>

struct tm *localtime(const time_t *clock)
{
	register long l, t;
	register int i;
	static struct tm tm;
	static int days[12] = {
		31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
	};

	l = *clock;
	tm.tm_sec = l % 60;
	l /= 60;
	tm.tm_min = l % 60;
	l /= 60;
	tm.tm_hour = l % 24;
	l /= 24;
	tm.tm_wday = (l+4)%7;	/* add 4 days since first day of 70 not sunday */
	tm.tm_year = 70 + (l/(4*365+1)) * 4;
	l %= 4 * 365 + 1;
	while (l) {
		t = 365;
		if ((tm.tm_year&3) == 0)
			t++;
		if (l < t)
			break;
		l -= t;
		tm.tm_year++;
	}
	tm.tm_yday = l++;
	for (i=0;i<12;i++) {
		t = days[i];
		if (i == 1 && (tm.tm_year&3) == 0)
			t++;
		if (l <= t)
			break;
		l -= t;
	}
	tm.tm_mon = i;
	tm.tm_mday = l;
	return(&tm);
}

makefile
CC=qcc
AS=as
CFLAGS=
AFLAGS=
O=oss

.c.$O:
	$(CC) -o $@ $(CFLAGS) $*.c
.a68.$O:
	$(AS) -o $@ $(AFLAGS) $*.a68

CLIB=\
	asctime.$O clock.$O ctime.$O difftime.$O gmtime.$O \
	localtime.$O mktime.$O strftime.$O time.$O
MLIB=\
	difftime.$O

clib:	$(CLIB)

mlib:	$(MLIB)

mktime.c
/* Copyright Manx Software Systems 1989. All rights reserved */

/*
 *	time_t mktime(struct tm *timeptr)
 *
 *	converts the broken-down time, expressed as local time, in the
 *	structure pointed to by timeptr into a calendar time value with
 *	the same encoding as that of the values returned by the time
 *	function. The original values of the tm_wday and tm_yday
 *	components of the structure are ignored, and the original values
 *	of the other components are not restricted to the ranges 
 *	specified for the tm structure. On successful completion, the
 *	values of the tm_wday and tm_yday components of the structure are
 *	set appropriately, and the other components are set to represent
 *	the specified calendar time, but with their values forced to the
 *	ranges indicated for the tm structure; the final value of tm_mday
 *	is not set until tm_mon and tm_year are determined.
 *
 *	returns the specified calendar time encoded as a value of type
 *	time_t. If the calendar time cannot be represented, the function
 *	returns the value (time_t)-1.
 */

#include <time.h>

#define SECS_IN_DAY		(60*60*24L) 
#define YEARS_IN_GOOGLE	4	/* google is a 4 year period including leap year */
#define DAYS_IN_GOOGLE	(4*365L+1)
#define SECS_IN_MIN		60
#define MIN_IN_HOUR		60
#define HOURS_IN_DAY	24
#define SECS_IN_HOUR	(60*60L)

time_t mktime(struct tm *timeptr)
{
	register int i, ry, ydays, year_day, years, googles;
	time_t ltime;
	static int days[12]={ 31,28,31,30,31,30,31,31,30,31,30,31 };

	if (timeptr->tm_sec < 0 || timeptr->tm_min < 0 ||
				timeptr->tm_hour < 0 || timeptr->tm_mday < 0 ||
						timeptr->tm_mon < 0 || timeptr->tm_year < 70)
		return(-1);

	ltime = timeptr->tm_sec;
	ltime += SECS_IN_MIN * timeptr->tm_min;
	ltime += SECS_IN_HOUR * timeptr->tm_hour;
	ltime += SECS_IN_DAY * (timeptr->tm_mday - 1);

 /* calculate the number of days already past in the current year */

	for (i=0,year_day=0;i<timeptr->tm_mon;i++) {
		year_day += days[i];
		if (i==1 && (timeptr->tm_year & 3) == 0)
			year_day++;
	}
	ltime += year_day * SECS_IN_DAY;
	years = timeptr->tm_year - 70;
	googles = years / YEARS_IN_GOOGLE;		/* number of googles since 1970 */
	ltime+= googles * DAYS_IN_GOOGLE * SECS_IN_DAY;
	ry= 70 + YEARS_IN_GOOGLE * googles;

 /* calculate number of days since last google */

	for (i=ry, ydays=0; i < timeptr->tm_year; i++) {
		ydays += 365;
		if ((i & 3) == 0)
			ydays++;
	}
	ltime += ydays * SECS_IN_DAY;
	*timeptr = *localtime(&ltime);
	return(ltime);
}

strftime.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	size_t strftime(char *s, size_t maxsize,
 *				const char *format, const struct tm *timeptr);
 *
 *	places characters into the array pointed to by s as controlled by the
 *	string pointed to by format. The format shall be a multibyte character
 *	sequence, beginning and ending in its initial shift state. The format
 *	string consists of zero or more conversion specifications and ordinary
 *	multibyte characters. A conversion specification consists of a %
 *	character followed by a character that determines the conversion
 *	specification's behavior. All ordinary multibyte characters (including
 *	the terminating null character) are copied unchanged into the array.
 *	No more than maxsize characters are placed into the array. Each
 *	conversion specification is replaced by appropriate characters as
 *	described in the following list. The appropriate characters are
 *	determined by the program's locale and by the values contained in the
 *	structure pointed to by timeptr.
 *
 *		%a	the locale's abbreviated weekday name.
 *		%A	the locale's full weekday name.
 *		%b	the locale's abbreviated month name.
 *		%B	the locale's full month name.
 *		%c	the locale's appropriate date and time representation.
 *		%d	the day of the month as a decimal number (01-31).
 *		%H	the hour (24-hour clock) as a decimal number (00-23).
 *		%I	the hour (12-hour clock) as a decimal number (01-12).
 *		%j	the day of the year as a decimal number (001-366).
 *		%m	the month as a decimal number (01-12).
 *		%M	the minute as a decimal number (00-59).
 *		%p	the locale's equivalent of either AM or PM.
 *		%S	the second as a decimal number (00-59).
 *		%U	the week number of the year (Sunday as the first day of the
 *			week) as a decimal number (00-53).
 *		%w	the weekday as a decimal number [0 (Sunday)-6].
 *		%W	the week number of the year (Monday as the first day of the
 *			week) as a decimal number (00-53).
 *		%x	the locale's appropriate date representation.
 *		%X	the locale's appropriate time representation.
 *		%y	the year without century as a decimal number (00-99).
 *		%Y	the year with century as a decimal number.
 *		%Z	the time zone name, or by no characters if no time zone is
 *			determinable.
 *		%%	the % character.
 *
 *	If a conversion specification is not one of the above, the behavior
 *	is undefined.
 *
 *	returns the number of characters placed into the array pointed to by s
 *	not including the terminating null character if the total number of
 *	resulting characters including the terminating null character is not
 *	more than maxsize. Otherwise, zero is returned and the contents of the
 *	array are indeterminate.
 */

#include <stdlib.h>
#include <string.h>
#include <time.h>

static char *abrwday[7] = {"Sun","Mon","Tues","Wed","Thurs","Fri","Sat"};

static char *wdays[7] = {"Sunday","Monday","Tuesday","Wednesday","Thursday",
					"Friday","Saturday"};

static char *abrmon[12] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug",
					"Sep","Oct","Nov","Dec"};

static char *mon[12] = {"January","February","March","April","May","June",
				"July","August","September","October","November","December"};

static char *itoa(int i, char res[5], int size);
static void dotime(char *cp,const struct tm *timeptr);

size_t
strftime(char *s, size_t maxsize, const char *format, const struct tm *timep)
{
	size_t n;
	char c, *env, *temp, *cp, buf[5], *getenv(), nbuf[35];
	int dwk0, wks, wday;
	register struct tm *timeptr;
	struct tm tm;

	tm = *timep;
	timeptr = &tm;
	(void)mktime(timeptr);
	temp = s;

	while (c = *format++) {
		n = maxsize - (temp - s);
		if (c=='%') {
			c = *format++;
			switch (c) {
			case 'a':		/* abbreviated weekday name */ 
				cp = abrwday[timeptr->tm_wday];
				break;
			case 'A':		/* full weekday name */
				cp = wdays[timeptr->tm_wday];
				break;
			case 'b':		/* abbreviated month name */
				cp = abrmon[timeptr->tm_mon];
				break;
			case 'B':		/* full month name */
				cp = mon[timeptr->tm_mon];
				break;
			case 'c':		/* date and time */
				cp = nbuf;
				strcpy(cp, abrwday[timeptr->tm_wday]);
				strcat(cp, " ");
				strcat(cp, abrmon[timeptr->tm_mon]);
				strcat(cp, " ");
				strcat(cp, itoa(timeptr->tm_mday, buf, 0));
				strcat(cp, " ");
				dotime(cp, timeptr);
				strcat(cp, " ");
				strcat(cp, itoa(timeptr->tm_year+1900, buf, 0));
				break;
			case 'd':		/* day of the month (0-31) */
				cp = itoa(timeptr->tm_mday,buf,2);
				break;
			case 'H':		/* 24-hour clock hour (0-23) */
				cp = itoa(timeptr->tm_hour,buf,2);
				break;
			case 'I':		/* 12-hour clock hour (1-12) */
				if (timeptr->tm_hour == 0)
					cp = itoa(12,buf,2);
				else if (timeptr->tm_hour > 12)
					cp = itoa(timeptr->tm_hour-12, buf,2);
				else
					cp = itoa(timeptr->tm_hour, buf, 2);
				break;
			case 'j':		/* day of the year (1-366) */
				cp = itoa(timeptr->tm_yday+1, buf, 3);
				break;
			case 'm':		/* month as a decimal number (1-12) */
				cp = itoa(timeptr->tm_mon+1, buf, 2);
				break;
			case 'M':		/* minute as a decimal number (0-59) */
				cp = itoa(timeptr->tm_min, buf, 2);
				break;
			case 'p':		/* AM or PM */
				if (timeptr->tm_hour < 11)
					cp = "AM";
				else
					cp = "PM";
				break;
			case 'S':		/* second as a decimal number (0-59) */
				cp = itoa(timeptr->tm_sec, buf, 2);
				break;
			case 'U':		/* week number of the year, Sunday as first
										day of the week (0-53) */
				dwk0 =	(timeptr->tm_yday - timeptr->tm_wday) % 7; 
				if (dwk0==0)
					dwk0=7;
				if (timeptr->tm_yday <= dwk0)
					wks = 0;
				else 
					wks = ((timeptr->tm_yday - dwk0)/ 7 ) +1;
				cp = itoa(wks, buf, 2);
				break;
			case 'w':		/* weekday as a decimal number (0(SUN)-6) */
				cp = itoa(timeptr->tm_wday, buf, 1);
				break;
			case 'W':		/* week number of the year, Monday as first
										day of the week (0-53) */
				wday = timeptr->tm_wday - 1;
				if (wday < 0)
					wday = 6;
				dwk0 =	(timeptr->tm_yday - wday) % 7; 
				if (dwk0 == 0)
					dwk0 = 7;
				if (timeptr->tm_yday <= dwk0)
					wks = 0;
				else 
					wks = ((timeptr->tm_yday - dwk0)/ 7 ) +1;
				cp = itoa(wks, buf, 2);
				break;
			case 'x':		/* date (Mon Aug 1, 1988) */
				cp=nbuf;
				strcpy(cp, abrwday[timeptr->tm_wday]);
				strcat(cp, " ");
				strcat(cp, abrmon[timeptr->tm_mon]);
				strcat(cp, " ");
				strcat(cp, itoa(timeptr->tm_mday, buf, 0));
				strcat(cp, ", ");
				strcat(cp, itoa(timeptr->tm_year+1900, buf, 0));
				break;
			case 'X':		/* time (10:23:57) */
				cp = nbuf;
				*cp = 0;
				dotime(cp, timeptr);
				break;
			case 'y':		/* year without century (0-99) */
				cp = itoa(timeptr->tm_year, buf, 2);
				break;
			case 'Y':		/* year with century */
				cp = itoa(timeptr->tm_year+1900, buf, 0);
				break;
			case 'Z':		/* time zone */
				env = getenv("TZ");
				if (env == 0)
					cp = "";
				else {
					cp = buf;
					strncpy(cp, env, (size_t)3);
					cp[3] = 0;
				}
				break;
			default:		/* always print character after % */
				buf[0] = c;
				buf[1] = 0;
				cp = buf;
				break;
			}
		}
		else {
			buf[0] = c;		/* copy character from format string to output */
			buf[1] = 0;
			cp = buf;
		}
		strncpy(temp, cp, n);
		if ( n <= strlen(cp))
			return(0);
		else
			temp += strlen(cp);
	} 
	return(temp - s);
}

/*add time to output string */
static void
dotime( char *cp,const struct tm *timeptr)
{
	char buf[5];

	strcat(cp, itoa(timeptr->tm_hour, buf, 2));
	strcat(cp, ":");
	strcat(cp, itoa(timeptr->tm_min, buf, 2));
	strcat(cp, ":");
	strcat(cp, itoa(timeptr->tm_sec, buf, 2));
}


/* convert decimal number to character string */ 
static char *
itoa(int i, char res[5], int cnt)
{
	char *cp = res + 5;

	*--cp = 0;
	do {
		*--cp = '0' + i%10;
		i /= 10;
	} while (i != 0);
	while (cp >= res + 5 - cnt)
		*--cp = '0';
	return(cp);
}

time.c
/* Copyright 1989 Manx Software Systems, Inc. All rights reserved */

/*
 *	time_t time(time_t *timer);
 *
 *	determines the current calendar time in seconds since January 1, 1970.
 *
 *	returns the best approximation to the current calendar time. The value
 *	(time_t)-1 is returned if the calendar time is not available. If timer
 *	is not a null pointer, the return value is also assigned to the object
 *	it points to.
 */

#if MPU68000

#if MCH_AMIGA

#include <exec/types.h>
#include <exec/lists.h>
#include <devices/timer.h>
#include <functions.h>
#include <time.h>

#define SECS70TO78	(2*(4*365L+1)*(60*60*24L))	/* 2 googles in 8 years */

time_t
time(time_t *tt)
{
	struct MsgPort *CreatePort();
	struct timerequest t;
	register time_t hz;

	if (OpenDevice(TIMERNAME, (long)UNIT_VBLANK, &t.tr_node, 0L) == 0) {
		t.tr_node.io_Message.mn_ReplyPort = CreatePort(0L, 0L);
		t.tr_node.io_Command = TR_GETSYSTIME;
		DoIO(&t.tr_node);
		hz = t.tr_time.tv_secs + (t.tr_time.tv_micro + 500000) / 1000000;
		CloseDevice(&t.tr_node);
		DeletePort(t.tr_node.io_Message.mn_ReplyPort);
		hz += SECS70TO78;
	}
	else
		hz = -1;

	if (tt)
		*tt = hz;
	return(hz);
}

#endif /* MCH_AMIGA */

#elif MPU8086

#include <time.h>

#if 0
#define SECS04TO70	(16*(4*365L+1)*(60*60*24L))
#endif
#define SECS04TO70	2019686400L

time_t 
time(time_t *tloc)
{
	unsigned long x;

	GetDateTime(&x);
	x-=(unsigned long)SECS04TO70;

	if (tloc)
		*tloc = x;

	return x;
}

#endif /* MPU8086 */

