]> xenbits.xensource.com Git - unikraft/libs/newlib.git/commitdiff
Add musl-imported time functions
authorEduard Vintilă <eduard.vintila47@gmail.com>
Sun, 9 Apr 2023 16:38:35 +0000 (19:38 +0300)
committerUnikraft <monkey@unikraft.io>
Mon, 8 May 2023 10:10:14 +0000 (10:10 +0000)
Signed-off-by: Eduard Vintilă <eduard.vintila47@gmail.com>
Reviewed-by: Maria Sfiraiala <maria.sfiraiala@gmail.com>
Reviewed-by: Teodor Tiron <teotiron@gmail.com>
Approved-by: Razvan Deaconescu <razvand@unikraft.io>
Tested-by: Unikraft CI <monkey@unikraft.io>
GitHub-Closes: #28

Makefile.uk
musl-imported/src/time/__month_to_secs.c [new file with mode: 0644]
musl-imported/src/time/__secs_to_tm.c [new file with mode: 0644]
musl-imported/src/time/__tm_to_secs.c [new file with mode: 0644]
musl-imported/src/time/__year_to_secs.c [new file with mode: 0644]
musl-imported/src/time/time_impl.h [new file with mode: 0644]
musl-imported/src/time/timegm.c [new file with mode: 0644]

index 55e1fca82bed4a2858ac5b94b19c6faa334b856c..87fdf2fee2319447da062af0ba566e29b3b9679d 100644 (file)
@@ -164,6 +164,11 @@ LIBNEWLIBGLUE_SRCS-y += $(LIBNEWLIBC_BASE)/musl-imported/src/termios/tcsetattr.c
 LIBNEWLIBGLUE_SRCS-y += $(LIBNEWLIBC_BASE)/musl-imported/src/termios/tcgetattr.c
 LIBNEWLIBGLUE_SRCS-y += $(LIBNEWLIBC_BASE)/musl-imported/src/math/sincosl.c
 LIBNEWLIBGLUE_SRCS-y += $(LIBNEWLIBC_BASE)/musl-imported/src/exit/assert.c
+LIBNEWLIBGLUE_SRCS-y += $(LIBNEWLIBC_BASE)/musl-imported/src/time/__month_to_secs.c
+LIBNEWLIBGLUE_SRCS-y += $(LIBNEWLIBC_BASE)/musl-imported/src/time/__secs_to_tm.c
+LIBNEWLIBGLUE_SRCS-y += $(LIBNEWLIBC_BASE)/musl-imported/src/time/__tm_to_secs.c
+LIBNEWLIBGLUE_SRCS-y += $(LIBNEWLIBC_BASE)/musl-imported/src/time/__year_to_secs.c
+LIBNEWLIBGLUE_SRCS-y += $(LIBNEWLIBC_BASE)/musl-imported/src/time/timegm.c
 LIBNEWLIBGLUE_SRCS-y += $(LIBNEWLIBC_BASE)/__uk_init_tls.c
 
 ifeq ($(CONFIG_LIBNEWLIBC_CRYPT),y)
diff --git a/musl-imported/src/time/__month_to_secs.c b/musl-imported/src/time/__month_to_secs.c
new file mode 100644 (file)
index 0000000..c3ae57f
--- /dev/null
@@ -0,0 +1,12 @@
+int __month_to_secs(int month, int is_leap)
+{
+       static const int secs_through_month[] = {
+               0, 31*86400, 59*86400, 90*86400,
+               120*86400, 151*86400, 181*86400, 212*86400,
+               243*86400, 273*86400, 304*86400, 334*86400 };
+       int t = secs_through_month[month];
+
+       if (is_leap && month >= 2)
+               t += 86400;
+       return t;
+}
diff --git a/musl-imported/src/time/__secs_to_tm.c b/musl-imported/src/time/__secs_to_tm.c
new file mode 100644 (file)
index 0000000..4a9f53a
--- /dev/null
@@ -0,0 +1,82 @@
+#include "time_impl.h"
+#include <limits.h>
+
+/* 2000-03-01 (mod 400 year, immediately after feb29 */
+#define LEAPOCH (946684800LL + 86400*(31+29))
+
+#define DAYS_PER_400Y (365*400 + 97)
+#define DAYS_PER_100Y (365*100 + 24)
+#define DAYS_PER_4Y   (365*4   + 1)
+
+int __secs_to_tm(long long t, struct tm *tm)
+{
+       long long days, secs, years;
+       int remdays, remsecs, remyears;
+       int qc_cycles, c_cycles, q_cycles;
+       int months;
+       int wday, yday, leap;
+       static const char days_in_month[] = {31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29};
+
+       /* Reject time_t values whose year would overflow int */
+       if (t < INT_MIN * 31622400LL || t > INT_MAX * 31622400LL)
+               return -1;
+
+       secs = t - LEAPOCH;
+       days = secs / 86400;
+       remsecs = secs % 86400;
+       if (remsecs < 0) {
+               remsecs += 86400;
+               days--;
+       }
+
+       wday = (3+days)%7;
+       if (wday < 0) wday += 7;
+
+       qc_cycles = days / DAYS_PER_400Y;
+       remdays = days % DAYS_PER_400Y;
+       if (remdays < 0) {
+               remdays += DAYS_PER_400Y;
+               qc_cycles--;
+       }
+
+       c_cycles = remdays / DAYS_PER_100Y;
+       if (c_cycles == 4) c_cycles--;
+       remdays -= c_cycles * DAYS_PER_100Y;
+
+       q_cycles = remdays / DAYS_PER_4Y;
+       if (q_cycles == 25) q_cycles--;
+       remdays -= q_cycles * DAYS_PER_4Y;
+
+       remyears = remdays / 365;
+       if (remyears == 4) remyears--;
+       remdays -= remyears * 365;
+
+       leap = !remyears && (q_cycles || !c_cycles);
+       yday = remdays + 31 + 28 + leap;
+       if (yday >= 365+leap) yday -= 365+leap;
+
+       years = remyears + 4*q_cycles + 100*c_cycles + 400LL*qc_cycles;
+
+       for (months = 0; days_in_month[months] <= remdays; months++)
+               remdays -= days_in_month[months];
+
+       if (months >= 10) {
+               months -= 12;
+               years++;
+       }
+
+       if (years+100 > INT_MAX || years+100 < INT_MIN)
+               return -1;
+
+       tm->tm_year = years + 100;
+       tm->tm_mon = months + 2;
+       tm->tm_mday = remdays + 1;
+       tm->tm_wday = wday;
+       tm->tm_yday = yday;
+
+       tm->tm_hour = remsecs / 3600;
+       tm->tm_min = remsecs / 60 % 60;
+       tm->tm_sec = remsecs % 60;
+
+       return 0;
+}
diff --git a/musl-imported/src/time/__tm_to_secs.c b/musl-imported/src/time/__tm_to_secs.c
new file mode 100644 (file)
index 0000000..aaf7d13
--- /dev/null
@@ -0,0 +1,27 @@
+#include "time_impl.h"
+
+long long __tm_to_secs(const struct tm *tm)
+{
+       int is_leap;
+       long long year = tm->tm_year;
+       int month = tm->tm_mon;
+
+       if (month >= 12 || month < 0) {
+               int adj = month / 12;
+
+               month %= 12;
+               if (month < 0) {
+                       adj--;
+                       month += 12;
+               }
+               year += adj;
+       }
+       long long t = __year_to_secs(year, &is_leap);
+
+       t += __month_to_secs(month, is_leap);
+       t += 86400LL * (tm->tm_mday-1);
+       t += 3600LL * tm->tm_hour;
+       t += 60LL * tm->tm_min;
+       t += tm->tm_sec;
+       return t;
+}
diff --git a/musl-imported/src/time/__year_to_secs.c b/musl-imported/src/time/__year_to_secs.c
new file mode 100644 (file)
index 0000000..16d71c5
--- /dev/null
@@ -0,0 +1,55 @@
+long long __year_to_secs(long long year, int *is_leap)
+{
+       if (year-2ULL <= 136) {
+               int y = year;
+               int leaps = (y-68)>>2;
+
+               if (!((y-68)&3)) {
+                       leaps--;
+                       if (is_leap)
+                               *is_leap = 1;
+               } else if (is_leap)
+                       *is_leap = 0;
+               return 31536000*(y-70) + 86400*leaps;
+       }
+
+       int cycles, centuries, leaps, rem;
+
+       if (!is_leap)
+               is_leap = &(int){0};
+       cycles = (year-100) / 400;
+       rem = (year-100) % 400;
+       if (rem < 0) {
+               cycles--;
+               rem += 400;
+       }
+       if (!rem) {
+               *is_leap = 1;
+               centuries = 0;
+               leaps = 0;
+       } else {
+               if (rem >= 200) {
+                       if (rem >= 300)
+                               centuries = 3, rem -= 300;
+                       else
+                               centuries = 2, rem -= 200;
+               } else {
+                       if (rem >= 100)
+                               centuries = 1, rem -= 100;
+                       else
+                               centuries = 0;
+               }
+               if (!rem) {
+                       *is_leap = 0;
+                       leaps = 0;
+               } else {
+                       leaps = rem / 4U;
+                       rem %= 4U;
+                       *is_leap = !rem;
+               }
+       }
+
+       leaps += 97*cycles + 24*centuries - *is_leap;
+
+       return (year-100) * 31536000LL + leaps * 86400LL + 946684800 + 86400;
+}
diff --git a/musl-imported/src/time/time_impl.h b/musl-imported/src/time/time_impl.h
new file mode 100644 (file)
index 0000000..5c1e362
--- /dev/null
@@ -0,0 +1,13 @@
+#include <time.h>
+
+int __days_in_month(int, int);
+int __month_to_secs(int, int);
+long long __year_to_secs(long long, int *);
+long long __tm_to_secs(const struct tm *);
+const char *__tm_to_tzname(const struct tm *);
+int __secs_to_tm(long long, struct tm *);
+void __secs_to_zone(long long, int, int *, long *, long *, const char **);
+#if 0
+const char *__strftime_fmt_1(char (*)[100], size_t *, int, const struct tm *, locale_t, int);
+#endif
+extern const char __utc[];
diff --git a/musl-imported/src/time/timegm.c b/musl-imported/src/time/timegm.c
new file mode 100644 (file)
index 0000000..f5b265f
--- /dev/null
@@ -0,0 +1,23 @@
+#define _GNU_SOURCE
+#include <uk/config.h>
+#include "time_impl.h"
+#include <errno.h>
+
+const char __utc[] = "UTC";
+
+time_t timegm(struct tm *tm)
+{
+       struct tm new;
+       long long t = __tm_to_secs(tm);
+
+       if (__secs_to_tm(t, &new) < 0) {
+               errno = EOVERFLOW;
+               return -1;
+       }
+       *tm = new;
+       tm->tm_isdst = 0;
+       tm->__tm_gmtoff = 0;
+       tm->__tm_zone = __utc;
+
+       return t;
+}