Update MentOs code to the latest development version.
This commit is contained in:
+399
@@ -0,0 +1,399 @@
|
||||
/// MentOS, The Mentoring Operating system project
|
||||
/// @file time.c
|
||||
/// @brief Clock functions.
|
||||
/// @copyright (c) 2014-2021 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include "time.h"
|
||||
#include "system/syscall_types.h"
|
||||
#include "sys/errno.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
|
||||
static const char *weekdays[] = {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
|
||||
};
|
||||
|
||||
static const char *months[] = {
|
||||
"January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"
|
||||
};
|
||||
|
||||
_syscall1(time_t, time, time_t *, t)
|
||||
|
||||
time_t difftime(time_t time1, time_t time2)
|
||||
{
|
||||
return time1 - time2;
|
||||
}
|
||||
|
||||
/// @brief Computes day of week
|
||||
/// @param y Year
|
||||
/// @param m Month of year (in range 1 to 12)
|
||||
/// @param d Day of month (in range 1 to 31)
|
||||
/// @return Day of week (in range 1 to 7)
|
||||
static inline int day_of_week(unsigned int y, unsigned int m, unsigned int d)
|
||||
{
|
||||
int h, j, k;
|
||||
// January and February are counted as months 13 and 14 of the previous year
|
||||
if (m <= 2) {
|
||||
m += 12;
|
||||
y -= 1;
|
||||
}
|
||||
// J is the century
|
||||
j = (int)(y / 100);
|
||||
// K the year of the century
|
||||
k = (int)(y % 100);
|
||||
// Compute H using Zeller's congruence
|
||||
h = (int)(d + (26 * (m + 1) / 10) + k + (k / 4) + (5 * j) + (j / 4));
|
||||
// Return the day of the week
|
||||
return ((h + 5) % 7) + 1;
|
||||
}
|
||||
|
||||
tm_t *localtime(const time_t *time)
|
||||
{
|
||||
static tm_t date;
|
||||
unsigned int a, b, c, d, e, f;
|
||||
time_t t = *time;
|
||||
// Negative Unix time values are not supported
|
||||
if (t < 1) {
|
||||
t = 0;
|
||||
}
|
||||
//Retrieve hours, minutes and seconds
|
||||
date.tm_sec = (int)(t % 60);
|
||||
t /= 60;
|
||||
date.tm_min = (int)(t % 60);
|
||||
t /= 60;
|
||||
date.tm_hour = (int)(t % 24);
|
||||
t /= 24;
|
||||
// Convert Unix time to date
|
||||
a = (unsigned int)((4 * t + 102032) / 146097 + 15);
|
||||
b = (unsigned int)(t + 2442113 + a - (a / 4));
|
||||
c = (20 * b - 2442) / 7305;
|
||||
d = b - 365 * c - (c / 4);
|
||||
e = d * 1000 / 30601;
|
||||
f = d - e * 30 - e * 601 / 1000;
|
||||
// January and February are counted as months 13 and 14 of the previous year
|
||||
if (e <= 13) {
|
||||
c -= 4716;
|
||||
e -= 1;
|
||||
} else {
|
||||
c -= 4715;
|
||||
e -= 13;
|
||||
}
|
||||
//Retrieve year, month and day
|
||||
date.tm_year = (int)c;
|
||||
date.tm_mon = (int)e;
|
||||
date.tm_mday = (int)f;
|
||||
// Calculate day of week.
|
||||
date.tm_wday = day_of_week(date.tm_year, date.tm_mon, date.tm_mday);
|
||||
return &date;
|
||||
}
|
||||
|
||||
size_t strftime(char *str, size_t maxsize, const char *format, const tm_t *timeptr)
|
||||
{
|
||||
if (format == NULL || str == NULL || maxsize <= 0) {
|
||||
return 0;
|
||||
}
|
||||
char *f = (char *)format;
|
||||
char *s = str;
|
||||
int value;
|
||||
size_t ret = 0;
|
||||
while ((*f) != '\0') {
|
||||
if ((*f) != '%') {
|
||||
(*s++) = (*f);
|
||||
} else {
|
||||
++f;
|
||||
switch (*f) {
|
||||
#if 0
|
||||
case 'a': /* locale's abbreviated weekday name */
|
||||
PUT_STRN(weekdays[timeptr->tm_wday], 3);
|
||||
break;
|
||||
|
||||
case 'A': /* locale's full weekday name */
|
||||
PUT_STR(weekdays[timeptr->tm_wday]);
|
||||
break;
|
||||
#endif
|
||||
case 'b': // Abbreviated month name
|
||||
{
|
||||
strncat(s, months[timeptr->tm_mon], 3);
|
||||
break;
|
||||
}
|
||||
case 'B': // Full month name
|
||||
{
|
||||
unsigned int i = (unsigned int)timeptr->tm_mon;
|
||||
strcat(s, months[i]);
|
||||
break;
|
||||
}
|
||||
case 'd': /* day of month as decimal number (01-31) */
|
||||
{
|
||||
value = timeptr->tm_mday;
|
||||
(*s++) = (char)('0' + ((value / 10) % 10));
|
||||
(*s++) = (char)('0' + (value % 10));
|
||||
break;
|
||||
}
|
||||
case 'H': /* hour (24-hour clock) as decimal (00-23) */
|
||||
{
|
||||
value = timeptr->tm_hour;
|
||||
(*s++) = (char)('0' + ((value / 10) % 10));
|
||||
(*s++) = (char)('0' + (value % 10));
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
case 'I': /* hour (12-hour clock) as decimal (01-12) */
|
||||
SPRINTF("%02d", ((timeptr->tm_hour + 11) % 12) + 1);
|
||||
break;
|
||||
#endif
|
||||
case 'j': // Day of year as decimal number (001-366)
|
||||
{
|
||||
value = timeptr->tm_yday;
|
||||
(*s++) = (char)('0' + ((value / 10) % 10));
|
||||
(*s++) = (char)('0' + (value % 10));
|
||||
break;
|
||||
}
|
||||
case 'm': // Month as decimal number (01-12)
|
||||
{
|
||||
value = timeptr->tm_mon;
|
||||
(*s++) = (char)('0' + ((value / 10) % 10));
|
||||
(*s++) = (char)('0' + (value % 10));
|
||||
break;
|
||||
}
|
||||
#if 0
|
||||
case 'M': /* month as decimal number (00-59) */
|
||||
SPRINTF("%02d", timeptr->tm_min);
|
||||
break;
|
||||
|
||||
case 'p': /* AM/PM designations (12-hour clock) */
|
||||
PUT_STR(timeptr->tm_hour < 12 ? "AM" : "PM");
|
||||
/* s.b. locale-specific */
|
||||
break;
|
||||
|
||||
case 'S': /* second as decimal number (00-61) */
|
||||
SPRINTF("%02d", timeptr->tm_sec);
|
||||
break;
|
||||
|
||||
case 'U': /* week of year (first Sunday = 1) (00-53) */
|
||||
case 'W': /* week of year (first Monday = 1) (00-53) */
|
||||
{
|
||||
int fudge = timeptr->tm_wday - timeptr->tm_yday % 7;
|
||||
if (*fp == 'W') {
|
||||
fudge--;
|
||||
}
|
||||
fudge = (fudge + 7) % 7; /* +7 so not negative */
|
||||
SPRINTF("%02d", (timeptr->tm_yday + fudge) / 7);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'w': /* weekday (0-6), Sunday is 0 */
|
||||
SPRINTF("%02d", timeptr->tm_wday);
|
||||
break;
|
||||
|
||||
case 'x': /* appropriate date representation */
|
||||
RECUR("%B %d, %Y"); /* s.b. locale-specific */
|
||||
break;
|
||||
|
||||
case 'X': /* appropriate time representation */
|
||||
RECUR("%H:%M:%S"); /* s.b. locale-specific */
|
||||
break;
|
||||
|
||||
case 'y': /* year without century as decimal (00-99) */
|
||||
SPRINTF("%02d", timeptr->tm_year % 100);
|
||||
break;
|
||||
|
||||
case 'Y': /* year with century as decimal */
|
||||
SPRINTF("%d", timeptr->tm_year + 1900);
|
||||
break;
|
||||
|
||||
case 'Z': /* time zone name or abbreviation */
|
||||
/* XXX %%% */
|
||||
break;
|
||||
|
||||
case '%':
|
||||
PUT_CH('%');
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
(*s++) = '%';
|
||||
(*s++) = (*f);
|
||||
}
|
||||
}
|
||||
++f;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#define PUT_CH(c) (ret < maxsize ? (*dp++ = (c), ret++) : 0)
|
||||
#define PUT_STR(str) \
|
||||
p = (char *)(str); \
|
||||
goto dostr;
|
||||
#define PUT_STRN(str, n) \
|
||||
p = (char *)(str); \
|
||||
len = (n); \
|
||||
goto dostrn;
|
||||
#define SPRINTF(fmt, arg) \
|
||||
sprintf(tmpbuf, fmt, arg); \
|
||||
p = tmpbuf; \
|
||||
goto dostr;
|
||||
#define RECUR(fmt) \
|
||||
{ \
|
||||
size_t r = strftime(dp, maxsize - ret, fmt, timeptr); \
|
||||
if (r <= 0) \
|
||||
return r; \
|
||||
dp += r; \
|
||||
ret += r; \
|
||||
}
|
||||
|
||||
char* fp = (char*) format;
|
||||
char* dp = s;
|
||||
size_t ret = 0;
|
||||
|
||||
if (format == NULL || s == NULL || maxsize <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (*fp != '\0') {
|
||||
char* p;
|
||||
int len;
|
||||
char tmpbuf[10];
|
||||
|
||||
if (*fp != '%') {
|
||||
PUT_CH(*fp++);
|
||||
continue;
|
||||
}
|
||||
|
||||
fp++;
|
||||
|
||||
switch (*fp) {
|
||||
|
||||
case 'a': /* locale's abbreviated weekday name */
|
||||
PUT_STRN(weekdays[timeptr->tm_wday], 3);
|
||||
break;
|
||||
|
||||
case 'A': /* locale's full weekday name */
|
||||
PUT_STR(weekdays[timeptr->tm_wday]);
|
||||
break;
|
||||
|
||||
case 'b': /* locale's abbreviated month name */
|
||||
PUT_STRN(months[timeptr->tm_mon], 3);
|
||||
break;
|
||||
|
||||
case 'B': /* locale's full month name */
|
||||
PUT_STR(months[timeptr->tm_mon]);
|
||||
break;
|
||||
|
||||
case 'c': /* appropriate date and time representation */
|
||||
RECUR("%X %x"); /* s.b. locale-specific */
|
||||
break;
|
||||
|
||||
case 'd': /* day of month as decimal number (01-31) */
|
||||
SPRINTF("%02d", timeptr->tm_mday);
|
||||
break;
|
||||
|
||||
case 'H': /* hour (24-hour clock) as decimal (00-23) */
|
||||
SPRINTF("%02d", timeptr->tm_hour);
|
||||
break;
|
||||
|
||||
case 'I': /* hour (12-hour clock) as decimal (01-12) */
|
||||
SPRINTF("%02d", ((timeptr->tm_hour + 11) % 12) + 1);
|
||||
break;
|
||||
|
||||
case 'j': /* day of year as decimal number (001-366) */
|
||||
SPRINTF("%03d", timeptr->tm_yday + 1);
|
||||
break;
|
||||
|
||||
case 'm': /* month as decimal number (01-12) */
|
||||
SPRINTF("%02d", timeptr->tm_mon + 1);
|
||||
break;
|
||||
|
||||
case 'M': /* month as decimal number (00-59) */
|
||||
SPRINTF("%02d", timeptr->tm_min);
|
||||
break;
|
||||
|
||||
case 'p': /* AM/PM designations (12-hour clock) */
|
||||
PUT_STR(timeptr->tm_hour < 12 ? "AM" : "PM");
|
||||
/* s.b. locale-specific */
|
||||
break;
|
||||
|
||||
case 'S': /* second as decimal number (00-61) */
|
||||
SPRINTF("%02d", timeptr->tm_sec);
|
||||
break;
|
||||
|
||||
case 'U': /* week of year (first Sunday = 1) (00-53) */
|
||||
case 'W': /* week of year (first Monday = 1) (00-53) */
|
||||
{
|
||||
int fudge = timeptr->tm_wday - timeptr->tm_yday % 7;
|
||||
if (*fp == 'W') {
|
||||
fudge--;
|
||||
}
|
||||
fudge = (fudge + 7) % 7; /* +7 so not negative */
|
||||
SPRINTF("%02d", (timeptr->tm_yday + fudge) / 7);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'w': /* weekday (0-6), Sunday is 0 */
|
||||
SPRINTF("%02d", timeptr->tm_wday);
|
||||
break;
|
||||
|
||||
case 'x': /* appropriate date representation */
|
||||
RECUR("%B %d, %Y"); /* s.b. locale-specific */
|
||||
break;
|
||||
|
||||
case 'X': /* appropriate time representation */
|
||||
RECUR("%H:%M:%S"); /* s.b. locale-specific */
|
||||
break;
|
||||
|
||||
case 'y': /* year without century as decimal (00-99) */
|
||||
SPRINTF("%02d", timeptr->tm_year % 100);
|
||||
break;
|
||||
|
||||
case 'Y': /* year with century as decimal */
|
||||
SPRINTF("%d", timeptr->tm_year + 1900);
|
||||
break;
|
||||
|
||||
case 'Z': /* time zone name or abbreviation */
|
||||
/* XXX %%% */
|
||||
break;
|
||||
|
||||
case '%':
|
||||
PUT_CH('%');
|
||||
break;
|
||||
|
||||
dostr:
|
||||
while (*p != '\0')
|
||||
PUT_CH(*p++);
|
||||
break;
|
||||
|
||||
dostrn:
|
||||
while (len-- > 0)
|
||||
PUT_CH(*p++);
|
||||
break;
|
||||
}
|
||||
|
||||
++fp;
|
||||
}
|
||||
if (ret >= maxsize) {
|
||||
s[maxsize - 1] = '\0';
|
||||
return 0;
|
||||
}
|
||||
*dp = '\0';
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
_syscall2(int, nanosleep, const timespec *, req, timespec *, rem)
|
||||
|
||||
unsigned int sleep(unsigned int seconds)
|
||||
{
|
||||
timespec req, rem;
|
||||
req.tv_sec = seconds;
|
||||
// Call the nanosleep.
|
||||
int __ret = nanosleep(&req, &rem);
|
||||
// If the call to the nanosleep is interrupted by a signal handler,
|
||||
// then it returns -1 with errno set to EINTR.
|
||||
if ((__ret == -1) && (errno == EINTR)) {
|
||||
return rem.tv_sec;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
_syscall2(int, getitimer, int, which, itimerval *, curr_value)
|
||||
|
||||
_syscall3(int, setitimer, int, which, const itimerval *, new_value, itimerval *, old_value)
|
||||
Reference in New Issue
Block a user