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;
}