shithub: scc

Download patch

ref: 31198f45160ad08b972e4e14272a08cb79393134
parent: f812d73e86aa308c373e06a170a1b3ba89ad5cb6
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri Aug 27 07:44:57 EDT 2021

libc: Update time to last version

This code is being updated out of the tree of scc and
it is time to synchroniza both copies now.

--- a/src/libc/libc.h
+++ b/src/libc/libc.h
@@ -1,21 +1,26 @@
-#define SUN      0
-#define MON      1
-#define TUE      2
-#define WED      3
-#define THU      4
-#define FRI      5
-#define SAT      6
+enum {
+	SUN,
+	MON,
+	TUE,
+	WED,
+	THU,
+	FRI,
+	SAT
+};
 
-#define JAN      0
-#define FEB      1
-#define DEC     11
+#define JAN 0
+#define FEB 1
+#define DEC 11
 
-#define EPOCH 1970
 #define FEBDAYS(y) ((_daysyear(y) == 366) ? 29 : 28)
-#define SECMIN     60
-#define SECHOUR    (60 * SECMIN)    /* 3600 */
-#define SECDAY     (24 * SECHOUR)   /* 86400 */
+#define EPOCH 1970
+#define MINYEAR 1900
+#define SECMIN 60
+#define SECHOUR (60 * SECMIN)    /* 3600 */
+#define SECDAY (24 * SECHOUR)   /* 86400 */
 
+struct tm;
+
 struct tzone {
 	char *name;
 	int gmtoff;
@@ -22,28 +27,27 @@
 	int isdst;
 };
 
-struct tm;
-
-extern void _tzset(void);
-extern int _daysyear(int year);
-extern int _newyear(int year);
 extern void *_getheap(void);
-extern int _dtoi(char);
 
+#ifdef stdin
+extern int _allocbuf(FILE *);
+extern int _flsbuf(FILE *);
+extern FILE *_fpopen(const char * restrict, const char *restrict,
+                     FILE *restrict);
+#endif
+
 #ifdef _TIME_H
-extern char *_tzname[2];
 extern time_t _tzstdoff, _tzdstoff;
 extern time_t _tzstart, _tzend;
-extern int _tzjulian;
-extern struct tzone tzones[];
-#endif
 
-#ifdef stdin
-extern int _flsbuf(FILE *fp);
-extern int _allocbuf(FILE *fp);
-extern FILE *_fpopen(const char * restrict fname,
-                     const char * restrict mode,
-                     FILE * restrict fp);
+extern time_t _systime(struct tm *);
 #endif
 
+extern void _tzset(void);
+extern int _daysyear(int);
+extern int _newyear(int);
+
+extern int _tzjulian;
 extern int _daysmon[12];
+extern char *_tzname[2];
+extern struct tzone tzones[];
--- a/src/libc/objs/common-objs.mk
+++ b/src/libc/objs/common-objs.mk
@@ -98,6 +98,7 @@
 	string/strtok.$O\
 	string/strxfrm.$O\
 	time/_daysyear.$O\
+	time/_newyear.$O\
 	time/asctime.$O\
 	time/ctime.$O\
 	time/difftime.$O\
@@ -105,3 +106,4 @@
 	time/localtime.$O\
 	time/mktime.$O\
 	time/strftime.$O\
+	time/tz.$O\
--- a/src/libc/time/Makefile
+++ b/src/libc/time/Makefile
@@ -5,6 +5,7 @@
 
 OBJS =\
 	_daysyear.$O\
+	_newyear.$O\
 	asctime.$O\
 	ctime.$O\
 	difftime.$O\
--- a/src/libc/time/_daysyear.c
+++ b/src/libc/time/_daysyear.c
@@ -1,6 +1,3 @@
-#include <time.h>
-#include "../libc.h"
-
 int _daysmon[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
 int
@@ -11,20 +8,4 @@
 	if (year%100 == 0 && year%400 != 0)
 		return 365;
 	return 366;
-}
-
-/*
- * Happy New Year!!!!
- */
-int
-_newyear(int year)
-{
-	int day;
-
-	year += 1900 - 1;
-	day = 1 + year + year/4;
-	day -= year/100;
-	day += year/400;
-
-	return day % 7;
 }
--- /dev/null
+++ b/src/libc/time/_newyear.c
@@ -1,0 +1,15 @@
+/*
+ * Happy New Year!!!!
+ */
+int
+_newyear(int year)
+{
+	int day;
+
+	year += 1900 - 1;
+	day = 1 + year + year/4;
+	day -= year/100;
+	day += year/400;
+
+	return day % 7;
+}
--- a/src/libc/time/asctime.c
+++ b/src/libc/time/asctime.c
@@ -1,11 +1,17 @@
 #include <time.h>
+
 #undef asctime
 
 char *
 asctime(const struct tm *tm)
 {
-	static char buf[30];
+	static char buf[26];
 
+	/*
+	 * buf has space for a text like "Sun Sep 16 01:03:52 1973\n\0"
+	 * and for this reason strftime cannot fail as the buffer is
+	 * long enough
+	 */
 	strftime(buf, sizeof(buf), "%c\n", tm);
 	return buf;
 }
--- a/src/libc/time/ctime.c
+++ b/src/libc/time/ctime.c
@@ -1,4 +1,5 @@
 #include <time.h>
+
 #undef ctime
 
 char *
--- a/src/libc/time/difftime.c
+++ b/src/libc/time/difftime.c
@@ -1,8 +1,9 @@
 #include <time.h>
+
 #undef difftime
 
 double
 difftime(time_t t1, time_t t2)
 {
-	return (double) (t1 - t2);
+	return t2 - t1;
 }
--- a/src/libc/time/gmtime.c
+++ b/src/libc/time/gmtime.c
@@ -1,27 +1,28 @@
 #include <time.h>
 
 #include "../libc.h"
+
 #undef gmtime
 
 struct tm *
-gmtime(const time_t *t)
+gmtime(const time_t *tim)
 {
-        static struct tm tm;
-        time_t sec, min, hour, year, day;
+	static struct tm tm;
+	time_t day;
 	int i;
 
-        tm.tm_sec = *t % SECDAY;
+	tm.tm_sec = *tim % SECDAY;
 	tm.tm_min = tm.tm_sec / 60;
 	tm.tm_sec %= 60;
 	tm.tm_hour = tm.tm_min / 60;
 	tm.tm_min %= 60;
-	day = *t / SECDAY;
+	day = *tim / SECDAY;
 
 	tm.tm_wday = (day + THU) % 7; /* 1/1/1970 was Thursday */
 
 	for (i = EPOCH; day >= _daysyear(i); ++i)
 		day -= _daysyear(i);
-        tm.tm_year = i - 1900;
+	tm.tm_year = i - 1900;
 	tm.tm_yday = day;
 
 	_daysmon[FEB] = FEBDAYS(tm.tm_year);
@@ -32,5 +33,5 @@
 
 	tm.tm_isdst = 0;
 
-        return &tm;
+	return &tm;
 }
--- a/src/libc/time/localtime.c
+++ b/src/libc/time/localtime.c
@@ -38,14 +38,10 @@
 	tm->tm_zone = _tzname[0];
 	tm->tm_isdst = 0;
 
-	if (_tzjulian	       &&
-	    ((yday + 1) < 60)  ||
-	    (FEBDAYS(tm->tm_year) < 29))
+	if (_tzjulian && yday+1 < 60 || FEBDAYS(tm->tm_year) < 29)
 		yday++;
 
-	if (yday >= _tzstart &&
-	    yday <= _tzend   &&
-	    tm->tm_hour >= 2) {
+	if (yday >= _tzstart && yday <= _tzend && tm->tm_hour >= 2) {
 		tm->tm_gmtoff = _tzdstoff;
 		tm->tm_zone = _tzname[1];
 		tm->tm_isdst = 1;
--- a/src/libc/time/mktime.c
+++ b/src/libc/time/mktime.c
@@ -2,23 +2,24 @@
 #include <time.h>
 
 #include "../libc.h"
+
 #undef mktime
 
 static int
-norm(int *val, int *next, int qty)
+norm(int *val, int *next, int max)
 {
 	int v = *val, n = *next, d;
 
 	if (v < 0) {
-		d = -v / qty + 1;
-		v += d * qty;
+		d = -v / max + 1;
+		v += d * max;
 		if (n > INT_MAX - d)
 			return 0;
 		n -= d;
 	}
-	if (v >= qty) {
-		d = v / qty;
-		v -= d * qty;
+	if (v >= max) {
+		d = v / max;
+		v -= d * max;
 		if (n < INT_MIN + d)
 			return 0;
 		n += d;
@@ -33,14 +34,18 @@
 normalize(struct tm *tm)
 {
 	int mon, day, year, yday;
-	struct tm aux = *tm;
 
-	if (!norm(&tm->tm_sec, &tm->tm_min, 60)   ||
-	    !norm(&tm->tm_min, &tm->tm_hour, 60)  ||
-	    !norm(&tm->tm_hour, &tm->tm_mday, 24) ||
-	    !norm(&tm->tm_mon, &tm->tm_year, 12)) {
+	/*
+	 * Normalize sec so that it doesn't over/underflow min
+	 * Normalize min so that it doesn't over/underflow hour
+	 * Normalize hour so that it doesn't over/underflow mday
+	 * Normalize month so that it doesn't over/underflow year
+	 */
+	if (!norm(&tm->tm_sec, &tm->tm_min, 60)
+	|| !norm(&tm->tm_min, &tm->tm_hour, 60)
+	|| !norm(&tm->tm_hour, &tm->tm_mday, 24)
+	|| !norm(&tm->tm_mon, &tm->tm_year, 12))
 		return 0;
-	}
 
 	if (tm->tm_year < 0)
 		return 0;
@@ -47,15 +52,23 @@
 
 	day = tm->tm_mday;
 	yday = 0;
-	year = 1900 + tm->tm_year;
+	year = MINYEAR + tm->tm_year;
+
+	if (year > _MAXYEAR)
+		return 0;
+
 	_daysmon[FEB] = FEBDAYS(year);
 
+	/*
+	 * Normalize mday so that it doesn't over/underflow month
+	 * Normalize month so that it doesn't over/underflow year
+	 */
 	for (mon = tm->tm_mon; day < 1; --mon) {
 		if (mon == JAN) {
-			if (year == 1900)
+			if (year == MINYEAR)
 				return 0;
 			year--;
-			_daysmon[FEB] = FEBDAYS(year);
+			_daysmon[FEB] = _febdays(year);
 			mon = DEC+1;
 		}
 		day += _daysmon[mon-1];
@@ -67,20 +80,20 @@
 			if (year == _MAXYEAR)
 				return 0;
 			year++;
-			_daysmon[FEB] = FEBDAYS(year);
+			_daysmon[FEB] = _febdays(year);
 			mon = JAN-1;
 		}
 	}
 
-	for (int i = 0; i < mon; i++)
+	for (int i = 0; i < mon; ++i)
 		yday += _daysmon[i];
 
 	tm->tm_mon = mon;
-	tm->tm_year = year - 1900;
+	tm->tm_year = year - MINYEAR;
 	tm->tm_mday = day;
 	tm->tm_yday = yday + day - 1;
 	tm->tm_wday = (_newyear(tm->tm_year) + tm->tm_yday) % 7;
-
+	tm->tm_isdst = 0;
 	return 1;
 }
 
@@ -87,29 +100,7 @@
 time_t
 mktime(struct tm *tm)
 {
-	int i, year, dst;
-	time_t t;
-	struct tm *aux;
-
 	if (!normalize(tm))
 		return -1;
-
-	t = 0;
-	year = tm->tm_year + 1900;
-	for (i = EPOCH; i < year; i++)
-		t += _daysyear(i) * SECDAY;
-
-	for (i = 0; i < tm->tm_mon; i++)
-		t += _daysmon[i] * SECDAY;
-
-	t += tm->tm_sec;
-	t += tm->tm_min * SECMIN;
-	t += tm->tm_hour * SECHOUR;
-	t += (tm->tm_mday-1) * SECDAY;
-
-	aux = localtime(&t);
-
-	t += aux->tm_gmtoff;
-
-	return t;
+	return _systime(tm);
 }
--- a/src/libc/time/strftime.c
+++ b/src/libc/time/strftime.c
@@ -1,7 +1,8 @@
-#include <time.h>
 #include <string.h>
+#include <time.h>
 
 #include "../libc.h"
+
 #undef strftime
 
 static char *days[] = {
@@ -30,9 +31,8 @@
 	return day - ny;
 }
 
-
 static int
-weeknum(struct tm* tm, int day)
+weeknum(struct tm *tm, int day)
 {
 	int fday, val;
 
@@ -48,7 +48,7 @@
 }
 
 static int
-isoyear(struct tm* tm)
+isoyear(struct tm *tm)
 {
 	int monday;
 
@@ -65,7 +65,7 @@
 }
 
 static int
-isoweek(struct tm* tm)
+isoweek(struct tm *tm)
 {
 	int year, monday, yday, val;
 
@@ -72,11 +72,10 @@
 	year = isoyear(tm);
 	monday = first(THU, year) - 3;
 	yday = tm->tm_yday;
-	if (year > tm->tm_year) {
+	if (year > tm->tm_year)
 		yday = tm->tm_mday - 31 + monday;
-	} else if (year < tm->tm_year) {
+	else if (year < tm->tm_year)
 		yday = _daysyear(year) + yday;
-	}
 	val = yday - monday;
 	val /= 7;
 	val++;
@@ -83,6 +82,14 @@
 	return val;
 }
 
+static int
+isoday(struct tm *tm)
+{
+	if (tm->tm_wday == 0)
+		return 7;
+	return tm->tm_wday;
+}
+
 static size_t
 sval(char *s, size_t siz, char **strs, int abrev, int idx, int max)
 {
@@ -134,10 +141,10 @@
 {
 	long off = tm->tm_gmtoff;
 
-	if (prec < 5) {
-		*s = '?';
-		return 1;
-	}
+        if (prec < 5) {
+                *s = '?';
+                return 1;
+        }
 
 	if (off >= 0) {
 		*s++ = '+';
@@ -153,15 +160,14 @@
 }
 
 size_t
-strftime(char * restrict s, size_t siz,
-         const char * restrict fmt,
-         const struct tm * restrict tm)
+strftime(char *restrict s, size_t maxsize,
+	 const char *restrict format, const struct tm *restrict timeptr)
 {
 	int ch, abrev, val, fill, width;
 	size_t n, inc;
 	char *tfmt;
 
-	for (n = siz-1; (ch = *fmt++) && n > 0; s += inc, n -= inc) {
+	for (n = --maxsize; (ch = *format++) && n > 0; s += inc, n -= inc) {
 		if (ch != '%') {
 			*s = ch;
 			inc = 1;
@@ -172,93 +178,53 @@
 		fill = '0';
 		width = 2;
 
-		if (*fmt == 'E' || *fmt == 'O') {
-			fmt++;
-		}
+		if (*format == 'E' || *format == 'O')
+			format++;
 
-		switch (*fmt++) {
-		case 'Z':
-			if (!tm->tm_zone)
-				break;
-			inc = sval(s, n, &tm->tm_zone, 0, 0, 1);
-			break;
+		switch (*format++) {
 		case 'a':
 			abrev = 1;
 		case 'A':
-			inc = sval(s, n, days, abrev, tm->tm_wday, 7);
+			inc = sval(s, n, days, abrev, timeptr->tm_wday, 7);
 			break;
 		case 'h':
 		case 'b':
 			abrev = 1;
 		case 'B':
-			inc = sval(s, n, months, abrev, tm->tm_mon, 12);
+			inc = sval(s, n, months, abrev, timeptr->tm_mon, 12);
 			break;
-		case 'p':
-			inc = sval(s, n, am_pm, 0, tm->tm_hour > 12, 2);
-			break;
 		case 'c':
 			tfmt = "%a %b %e %T %Y";
 			goto recursive;
+		case 'C':
+			val = (timeptr->tm_year + 1900) / 100;
+			goto number;
+		case 'd':
+			val = timeptr->tm_mday;
+			goto number;
 		case 'D':
 			tfmt = "%m/%d/%y";
 			goto recursive;
-		case 'F':
-			tfmt = "%Y-%m-%d";
-			goto recursive;
-		case 'R':
-			tfmt = "%H:%M";
-			goto recursive;
-		case 'X':
-		case 'T':
-			tfmt = "%H:%M:%S";
-			goto recursive;
-		case 'r':
-			tfmt = "%I:%M:%S %p";
-			goto recursive;
-		case 'x':
-			tfmt = "%m/%d/%y";
-			goto recursive;
-		recursive:
-			inc = strftime(s, n+1, tfmt, tm) - 1;
-			break;
-		case 'n':
-			val = '\n';
-			goto character;
-		case 't':
-			val = '\t';
-			goto character;
-		case '%':
-			val = '%';
-		character:
-			*s = val;
-			inc = 1;
-			break;
 		case 'e':
 			fill = ' ';
-			val = tm->tm_mday;
+			val = timeptr->tm_mday;
 			goto number;
-		case 'd':
-			val = tm->tm_mday;
-			goto number;
-		case 'V':
-			val = isoweek(tm);
-			goto number;
+		case 'F':
+			tfmt = "%Y-%m-%d";
+			goto recursive;
 		case 'g':
-			val = isoyear(tm);
+			val = isoyear(timeptr);
 			goto number;
 		case 'G':
-			val = isoyear(tm);
+			val = isoyear(timeptr);
 			val += 1900;
 			width = 4;
 			goto number;
-		case 'C':
-			val = (tm->tm_year + 1900) / 100;
-			goto number;
 		case 'H':
-			val = tm->tm_hour;
+			val = timeptr->tm_hour;
 			goto number;
 		case 'I':
-			val = tm->tm_hour;
+			val = timeptr->tm_hour;
 			if (val == 0)
 				val = 12;
 			if (val > 12)
@@ -266,50 +232,89 @@
 			goto number;
 		case 'j':
 			width = 3;
-			val = tm->tm_yday+1;
+			val = timeptr->tm_yday+1;
 			goto number;
 		case 'm':
-			val = tm->tm_mon+1;
+			val = timeptr->tm_mon+1;
 			goto number;
 		case 'M':
-			val = tm->tm_min;
+			val = timeptr->tm_min;
 			goto number;
+		case 'n':
+			val = '\n';
+			goto character;
+		case 'p':
+			inc = sval(s, n, am_pm, 0, timeptr->tm_hour > 12, 2);
+			break;
+		case 'r':
+			tfmt = "%I:%M:%S %p";
+			goto recursive;
+		case 'R':
+			tfmt = "%H:%M";
+			goto recursive;
 		case 'S':
-			val = tm->tm_sec;
+			val = timeptr->tm_sec;
 			goto number;
+		case 't':
+			val = '\t';
+			goto character;
 		case 'u':
 			width = 1;
-			val = tm->tm_wday+1;
+			val = isoday(timeptr);
 			goto number;
 		case 'U':
-			val = weeknum(tm, SUN);
+			val = weeknum(timeptr, SUN);
 			goto number;
-		case 'W':
-			val = weeknum(tm, MON);
+		case 'V':
+			val = isoweek(timeptr);
 			goto number;
 		case 'w':
 			width = 1;
-			val = tm->tm_wday;
+			val = timeptr->tm_wday;
 			goto number;
+		case 'W':
+			val = weeknum(timeptr, MON);
+			goto number;
+		case 'X':
+		case 'T':
+			tfmt = "%H:%M:%S";
+			goto recursive;
+		case 'x':
+			tfmt = "%m/%d/%y";
+			goto recursive;
 		case 'y':
-			val = tm->tm_year%100;
+			val = timeptr->tm_year%100;
 			goto number;
 		case 'Y':
 			width = 4;
-			val = 1900 + tm->tm_year;
-		number:
-			inc = dval(s, n, width, fill, val);
-			break;
+			val = 1900 + timeptr->tm_year;
+			goto number;
 		case 'z':
-			inc = timezone(s, n, tm);
+			inc = timezone(s, n, timeptr);
 			break;
+		case 'Z':
+			memcpy(s, timeptr->tm_zone, 3);
+			inc = 3;
+			break;
 		case '\0':
 			inc = 0;
-			--fmt;
+			--format;
 			break;
+		case '%':
+			val = '%';
+		character:
+			*s = val;
+			inc = 1;
+			break;
+		number:
+			inc = dval(s, n, width, fill, val);
+			break;
+		recursive:
+			inc = strftime(s, n+1, tfmt, timeptr);
+			break;
 		}
 	}
 	*s = '\0';
 
-	return siz - n;
+	return maxsize - n;
 }