From: John Hodge Date: Sat, 8 Mar 2014 06:01:35 +0000 (+0800) Subject: Usermode/libc - C++ wrapping in headers, time rework X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=2610c32930309a73308f64731a05f2e83487b731;p=tpg%2Facess2.git Usermode/libc - C++ wrapping in headers, time rework --- diff --git a/Usermode/Libraries/libc.so_src/Makefile b/Usermode/Libraries/libc.so_src/Makefile index 4c37d186..3c18c28d 100644 --- a/Usermode/Libraries/libc.so_src/Makefile +++ b/Usermode/Libraries/libc.so_src/Makefile @@ -12,7 +12,7 @@ INCFILES := stdio.h stdlib.h OBJ = stub.o heap.o stdlib.o env.o stdio.o string.o rand.o OBJ += scanf.o signals.o strtoi.o strtof.o -OBJ += printf.o time.o errno.o +OBJ += printf.o time.o timeconv.o errno.o ctype.o OBJ += arch/$(ARCHDIR).ao # signals.o DEPFILES := $(OBJ:%.o=%.d) diff --git a/Usermode/Libraries/libc.so_src/ctype.c b/Usermode/Libraries/libc.so_src/ctype.c new file mode 100644 index 00000000..d5a5e97a --- /dev/null +++ b/Usermode/Libraries/libc.so_src/ctype.c @@ -0,0 +1,63 @@ +/* + * Acess2 C Library + * - By John Hodge (thePowersGang) + * + * ctype.c + * - Character Types + */ +#include + +int isalpha(int ch) +{ + if('A'<=ch&&ch<='Z') return 1; + if('a'<=ch&&ch<='z') return 1; + return 0; +} +int isdigit(int ch) { + if('0'<=ch&&ch<='9') return 1; + return 0; +} + +int isalnum(int ch) { + return isalpha(ch) || isdigit(ch); +} + +int toupper(int ch) { + if('a'<=ch && ch <='z') + return ch - 'a' + 'A'; + return ch; +} +int tolower(int ch) { + if('A'<=ch && ch <='Z') + return ch - 'A' + 'a'; + return ch; +} + +int isprint(int ch ) { + if( ch < ' ' ) return 0; + if( ch > 'z' ) return 0; + return 1; +} + +int isspace(int ch) { + if(ch == ' ') return 1; + if(ch == '\t') return 1; + if(ch == '\r') return 1; + if(ch == '\n') return 1; + return 0; +} + +int isxdigit(int ch) { + if('0'<=ch&&ch<='9') return 1; + if('a'<=ch&&ch<='f') return 1; + if('F'<=ch&&ch<='F') return 1; + return 0; +} + +// C99 +int isblank(int ch) { + if(ch == ' ') return 1; + if(ch == '\t') return 1; + return 0; +} + diff --git a/Usermode/Libraries/libc.so_src/errno.c b/Usermode/Libraries/libc.so_src/errno.c index e2948d6c..6f954574 100644 --- a/Usermode/Libraries/libc.so_src/errno.c +++ b/Usermode/Libraries/libc.so_src/errno.c @@ -45,6 +45,7 @@ EXPORT char *strerror(int errnum) case EPERM: return "Operation not permitted"; case ENOTTY: return "Not a TTY"; case EAGAIN: return "Try again"; + case EFBIG: return "File too big"; case EALREADY: return "Operation was no-op"; case EAFNOSUPPORT: return "Address family not supported"; case EINTERNAL: return "Internal error"; diff --git a/Usermode/Libraries/libc.so_src/include_exp/assert.h b/Usermode/Libraries/libc.so_src/include_exp/assert.h index dde4aeeb..d7029e56 100644 --- a/Usermode/Libraries/libc.so_src/include_exp/assert.h +++ b/Usermode/Libraries/libc.so_src/include_exp/assert.h @@ -8,6 +8,10 @@ #ifndef _LIBC__ASSERT_H_ #define _LIBC__ASSERT_H_ +#ifdef __cplusplus +extern "C" { +#endif + #include //#include #include @@ -20,5 +24,9 @@ # define assert(expr) do{if(!(expr)) { _SysDebug("%s:%i: Assertion '%s' failed", __FILE__, __LINE__, #expr); exit(-1);}}while(0) #endif +#ifdef __cplusplus +} +#endif + #endif diff --git a/Usermode/Libraries/libc.so_src/include_exp/ctype.h b/Usermode/Libraries/libc.so_src/include_exp/ctype.h index 60753a64..75e4ce88 100644 --- a/Usermode/Libraries/libc.so_src/include_exp/ctype.h +++ b/Usermode/Libraries/libc.so_src/include_exp/ctype.h @@ -8,51 +8,29 @@ #ifndef _CTYPE_H_ #define _CTYPE_H_ -static inline int isalpha(int ch) { - if('A'<=ch&&ch<='Z') return 1; - if('a'<=ch&&ch<='z') return 1; - return 0; -} -static inline int isdigit(int ch) { - if('0'<=ch&&ch<='9') return 1; - return 0; -} +#ifdef __cplusplus +extern "C" { +#endif -static inline int isalnum(int ch) { - return isalpha(ch) || isdigit(ch); -} +extern int isalpha(int ch); +extern int isdigit(int ch); -static inline int toupper(int ch) { - if('a'<=ch && ch <='z') - return ch - 'a' + 'A'; - return ch; -} -static inline int tolower(int ch) { - if('A'<=ch && ch <='Z') - return ch - 'A' + 'a'; - return ch; -} +extern int isalnum(int ch); -static inline int isspace(int ch) { - if(ch == ' ') return 1; - if(ch == '\t') return 1; - if(ch == '\r') return 1; - if(ch == '\n') return 1; - return 0; -} +extern int toupper(int ch); +extern int tolower(int ch); -static inline int isxdigit(int ch) { - if('0'<=ch&&ch<='9') return 1; - if('a'<=ch&&ch<='f') return 1; - if('F'<=ch&&ch<='F') return 1; - return 0; -} +extern int isprint(int ch); + +extern int isspace(int ch); + +extern int isxdigit(int ch); // C99 -static inline int isblank(int ch) { - if(ch == ' ') return 1; - if(ch == '\t') return 1; - return 0; +extern int isblank(int ch); + +#ifdef __cplusplus } +#endif #endif diff --git a/Usermode/Libraries/libc.so_src/include_exp/errno.enum.h b/Usermode/Libraries/libc.so_src/include_exp/errno.enum.h index 6d33bd49..f9436547 100755 --- a/Usermode/Libraries/libc.so_src/include_exp/errno.enum.h +++ b/Usermode/Libraries/libc.so_src/include_exp/errno.enum.h @@ -27,6 +27,8 @@ enum libc_eErrorNumbers { EAGAIN, // Try again EALREADY, // Operation was a NOP + + EFBIG, // File too large // psockets EAFNOSUPPORT, diff --git a/Usermode/Libraries/libc.so_src/include_exp/setjmp.h b/Usermode/Libraries/libc.so_src/include_exp/setjmp.h index fe545af2..5eb7bb5e 100644 --- a/Usermode/Libraries/libc.so_src/include_exp/setjmp.h +++ b/Usermode/Libraries/libc.so_src/include_exp/setjmp.h @@ -8,6 +8,10 @@ #ifndef _LIBC_SETJMP_H_ #define _LIBC_SETJMP_H_ +#ifdef __cplusplus +extern "C" { +#endif + #if defined(__i386__) typedef void *jmp_buf[8]; #elif defined(__amd64__) @@ -19,5 +23,9 @@ typedef void *jmp_buf[16]; extern int setjmp(jmp_buf buf); extern void longjmp(jmp_buf buf, int val); +#ifdef __cplusplus +} +#endif + #endif diff --git a/Usermode/Libraries/libc.so_src/include_exp/signal.h b/Usermode/Libraries/libc.so_src/include_exp/signal.h index a4c8bd3f..38de258c 100644 --- a/Usermode/Libraries/libc.so_src/include_exp/signal.h +++ b/Usermode/Libraries/libc.so_src/include_exp/signal.h @@ -8,6 +8,10 @@ #ifndef _SIGNAL_H_ #define _SIGNAL_H_ +#ifdef __cplusplus +extern "C" { +#endif + #include "signal_list.h" typedef void (*sighandler_t)(int); @@ -15,9 +19,9 @@ typedef void (*sighandler_t)(int); //! Atomic integer type typedef volatile int sig_atomic_t; -#define SIG_IGN ((void*)1) -#define SIG_DFL ((void*)0) -#define SIG_ERR ((void*)-1) +#define SIG_IGN ((sighandler_t)1) +#define SIG_DFL ((sighandler_t)0) +#define SIG_ERR ((sighandler_t)-1) extern sighandler_t signal(int signum, sighandler_t handler); @@ -55,5 +59,9 @@ struct sigaction extern int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); +#if __cplusplus +} +#endif + #endif diff --git a/Usermode/Libraries/libc.so_src/include_exp/stdio.h b/Usermode/Libraries/libc.so_src/include_exp/stdio.h index 4d812a7b..ed1fce58 100644 --- a/Usermode/Libraries/libc.so_src/include_exp/stdio.h +++ b/Usermode/Libraries/libc.so_src/include_exp/stdio.h @@ -9,6 +9,10 @@ #include #include // size_t +#ifdef __cplusplus +extern "C" { +#endif + /* === Types === */ typedef struct sFILE FILE; @@ -58,6 +62,8 @@ typedef struct sFILE FILE; #define getchar acess_getchar #define putchar acess_putchar +#define rename acess_rename + #define fprintf acess_fprintf #define vfprintf acess_vfprintf @@ -86,10 +92,13 @@ extern FILE *freopen(const char *file, const char *mode, FILE *fp); extern FILE *fmemopen(void *buffer, size_t length, const char *mode); extern FILE *open_memstream(char **bufferptr, size_t *lengthptr); extern FILE *fdopen(int fd, const char *modes); +extern FILE *tmpfile(void); extern int fclose(FILE *fp); extern void fflush(FILE *fp); extern off_t ftell(FILE *fp); +extern off_t ftello(FILE *fp); extern int fseek(FILE *fp, long int amt, int whence); +extern int fseeko(FILE *fp, off_t amt, int whence); extern void clearerr(FILE *stream); extern int feof(FILE *stream); extern int ferror(FILE *stream); @@ -109,6 +118,8 @@ extern int putchar(int ch); extern int fprintf(FILE *fp, const char *format, ...); extern int vfprintf(FILE *fp, const char *format, va_list args); +extern int rename(const char *oldpath, const char *newpath); + // scanf extern int scanf(const char *format, ...); extern int fscanf(FILE *stream, const char *format, ...); @@ -121,5 +132,9 @@ extern FILE *stdin; extern FILE *stdout; extern FILE *stderr; +#if __cplusplus +} +#endif + #endif diff --git a/Usermode/Libraries/libc.so_src/include_exp/stdlib.h b/Usermode/Libraries/libc.so_src/include_exp/stdlib.h index 7169150a..07fc81f4 100644 --- a/Usermode/Libraries/libc.so_src/include_exp/stdlib.h +++ b/Usermode/Libraries/libc.so_src/include_exp/stdlib.h @@ -9,6 +9,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define EXIT_FAILURE 1 #define EXIT_SUCCESS 0 @@ -31,6 +35,8 @@ # define labs acess_labs # define llabs acess_llabs +# define mktemp acess_mktemp + # define getenv acess_getenv # define putenv acess_putenv @@ -62,6 +68,8 @@ extern long strtol(const char *ptr, char **end, int base); extern unsigned long long strtoull(const char *ptr, char **end, int base); extern unsigned long strtoul(const char *ptr, char **end, int base); extern int atoi(const char *ptr); +extern long atol(const char *ptr); +extern long long atoll(const char *ptr); extern double strtod(const char *ptr, char **end); extern float strtof(const char *ptr, char **end); @@ -74,6 +82,8 @@ extern int abs(int j); extern long int labs(long int j); extern long long int llabs(long long int j); +extern char *mktemp(char *__template); + /* --- Environment --- */ extern char *getenv(const char *name); extern int putenv(char *string); @@ -102,4 +112,10 @@ extern int rand_p(unsigned int *seedp); # define SEEK_END (-1) #endif +#ifdef __cplusplus +} +#endif + +#include + #endif diff --git a/Usermode/Libraries/libc.so_src/include_exp/string.h b/Usermode/Libraries/libc.so_src/include_exp/string.h index 493d5efe..7ef1bc7a 100644 --- a/Usermode/Libraries/libc.so_src/include_exp/string.h +++ b/Usermode/Libraries/libc.so_src/include_exp/string.h @@ -7,6 +7,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Strings */ extern size_t strlen(const char *string); extern size_t strnlen(const char *string, size_t maxlen); @@ -26,6 +30,9 @@ extern char *strstr(const char *str1, const char *str2); extern size_t strcspn(const char *haystack, const char *reject); extern size_t strspn(const char *haystack, const char *accept); +extern char *strtok(char *str, const char *delim); +extern char *strtok_r(char *str, const char *delim, char **saveptr); + /* Memory */ extern void *memset(void *dest, int val, size_t count); extern void *memcpy(void *dest, const void *src, size_t count); @@ -33,4 +40,8 @@ extern void *memmove(void *dest, const void *src, size_t count); extern int memcmp(const void *mem1, const void *mem2, size_t count); extern void *memchr(const void *ptr, int value, size_t num); +#ifdef __cplusplus +} +#endif + #endif diff --git a/Usermode/Libraries/libc.so_src/include_exp/time.h b/Usermode/Libraries/libc.so_src/include_exp/time.h index 8480d68d..4c8d3ea6 100644 --- a/Usermode/Libraries/libc.so_src/include_exp/time.h +++ b/Usermode/Libraries/libc.so_src/include_exp/time.h @@ -11,6 +11,10 @@ #include // time_t #include // size_t +#ifdef __cplusplus +extern "C" { +#endif + struct tm { int tm_sec; // 0-60 @@ -47,16 +51,24 @@ extern time_t time(time_t *t); // //! Convert the time structure into a string of form 'Sun Sep 16 01:03:52 1973\n\0' extern char *asctime(const struct tm *timeptr); +extern char *asctime_r(const struct tm *timeptr, char *buf); //! asctime(localtime(timer)) extern char *ctime(const time_t *timer); +extern char *ctime_r(const time_t *timer, struct tm *result); //! Convert \a timter into UTC extern struct tm *gmtime(const time_t *timer); +extern struct tm *gmtime_r(const time_t *timer, struct tm *result); extern struct tm *localtime(const time_t *timer); +extern struct tm *localtime_r(const time_t *timep, struct tm *result); + +extern size_t strftime(char*s, size_t maxsize, const char*format, const struct tm*timeptr); -extern size_t strftime(char*restrict s, size_t maxsize, const char*restrict format, const struct tm*restrict timeptr); +#ifdef __cplusplus +}; +#endif #include diff --git a/Usermode/Libraries/libc.so_src/stdio.c b/Usermode/Libraries/libc.so_src/stdio.c index e98ca42a..a944f9b6 100644 --- a/Usermode/Libraries/libc.so_src/stdio.c +++ b/Usermode/Libraries/libc.so_src/stdio.c @@ -223,6 +223,33 @@ EXPORT FILE *open_memstream(char **bufferptr, size_t *lengthptr) return ret; } +EXPORT FILE *fdopen(int fd, const char *mode) +{ + FILE *ret; + + if( fd < 0 || !mode ) return NULL; + + ret = get_file_struct(); + + ret->FD = fd; + ret->Flags = _fopen_modetoflags(mode); + if(ret->Flags == -1) { + ret->Flags = 0; + return NULL; + } + + ret->Buffer = NULL; + ret->BufferPos = 0; + ret->BufferSpace = 0; + + return ret; +} + +EXPORT FILE *tmpfile(void) +{ + return NULL; +} + EXPORT int fclose(FILE *fp) { if( !(fp->Flags & FILE_FLAG_ALLOC) ) @@ -452,7 +479,7 @@ int _fseek_memstream(FILE *fp, long int amt, int whence) return 0; } -EXPORT int fseek(FILE *fp, long int amt, int whence) +EXPORT int fseeko(FILE *fp, off_t amt, int whence) { if(!fp || fp->FD == FD_NOTOPEN) { errno = EBADF; @@ -473,6 +500,11 @@ EXPORT int fseek(FILE *fp, long int amt, int whence) } } +EXPORT int fseek(FILE *fp, long int amt, int whence) +{ + return fseeko(fp, amt, whence); +} + size_t _fwrite_unbuffered(FILE *fp, size_t size, size_t num, const void *data) { size_t ret = 0, bytes; diff --git a/Usermode/Libraries/libc.so_src/string.c b/Usermode/Libraries/libc.so_src/string.c index 6ee6d6ca..aa79ec96 100644 --- a/Usermode/Libraries/libc.so_src/string.c +++ b/Usermode/Libraries/libc.so_src/string.c @@ -7,6 +7,7 @@ #include #include #include "lib.h" +#include /** * \fn EXPORT int strcmp(const char *s1, const char *s2) @@ -367,3 +368,35 @@ EXPORT size_t strspn(const char *haystack, const char *accept) } return ret; } + +char *strtok(char *str, const char *delim) +{ + static char *__saveptr; + return strtok_r(str, delim, &__saveptr); +} +char *strtok_r(char *str, const char *delim, char **saveptr) +{ + char *pos = (str ? str : *saveptr); + + while( strchr(delim, *pos) ) + pos ++; + + if( *pos == '\0' ) + return NULL; + + char *ret = pos; + while( !strchr(delim, *pos) ) + pos ++; + + // Cap the returned string + // - If we're at the end of the original string, don't shift pos + if( *pos != '\0' ) { + *pos = '\0'; + pos ++; + } + + *saveptr = pos; + + return ret; +} + diff --git a/Usermode/Libraries/libc.so_src/time.c b/Usermode/Libraries/libc.so_src/time.c index 412475b3..330b6a7d 100644 --- a/Usermode/Libraries/libc.so_src/time.c +++ b/Usermode/Libraries/libc.so_src/time.c @@ -8,12 +8,34 @@ #include #include #include +#include "timeconv.h" +#include + +#define UNIX_TO_2K ((30*365*3600*24) + (7*3600*24)) //Normal years + leap years clock_t clock(void) { return _SysTimestamp(); } +time_t mktime(struct tm *timeptr) +{ + time_t ret = seconds_since_y2k( + timeptr->tm_year - 2000, + timeptr->tm_mon, + timeptr->tm_mday, + timeptr->tm_hour, + timeptr->tm_min, + timeptr->tm_sec + ); + if( ret == 0 && errno ) { + // Bad date + } + ret += UNIX_TO_2K; + + return ret; +} + time_t time(time_t *t) { time_t ret = _SysTimestamp() / 1000; @@ -26,22 +48,26 @@ static struct tm static_tm; struct tm *localtime(const time_t *timer) { - struct tm *ret = &static_tm; + return localtime_r(timer, &static_tm); - // TODO: This breaks on negative timestamps - - int64_t day = *timer / (1000*60*60*24); - int64_t iday = *timer % (1000*60*60*24); +} +struct tm *localtime_r(const time_t *timer, struct tm *ret) +{ + // Hours, Mins, Seconds + int64_t days = get_days_since_y2k(*timer, &ret->tm_hour, &ret->tm_min, &ret->tm_sec); + + // Week day + ret->tm_wday = (days + 6) % 7; // Sun = 0, 1 Jan 2000 was Sat (6) + + // Year and Day of Year + bool is_ly; + ret->tm_year = 2000 + get_years_since_y2k(days, &is_ly, &ret->tm_yday); - ret->tm_sec = (iday / 1000) % 60;; - ret->tm_min = (iday / (1000*60)) % 60; - ret->tm_hour = (iday / (1000*60*60)); - ret->tm_year = 0; - ret->tm_mon = 0; - ret->tm_mday = 0; - ret->tm_wday = (day + 6) % 7; // 1 Jan 2000 was a saturday - ret->tm_yday = 0; + // Month and Day of Month + get_month_day(ret->tm_yday, is_ly, &ret->tm_mon, &ret->tm_mday); + ret->tm_isdst = 0; // Fuck DST + return ret; } diff --git a/Usermode/Libraries/libc.so_src/timeconv.c b/Usermode/Libraries/libc.so_src/timeconv.c new file mode 100644 index 00000000..6fed585a --- /dev/null +++ b/Usermode/Libraries/libc.so_src/timeconv.c @@ -0,0 +1,206 @@ +/* + * Acess2 C Library + * - By John Hodge (thePowersGang) + * + * timeconv.c + * - Shared User/Kernel time conversion code + */ +#include "timeconv.h" +#include + +#define ENABLE_LEAP_SECONDS 1 + +static const short DAYS_IN[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +static const short DAYS_BEFORE[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; +#define DEC31 365 +#define JUN30 181 + +#if ENABLE_LEAP_SECONDS +// Leap seconds after 2000 (stored as day numbers of application) +// - Leap seconds apply after the last second of said day (23:59:60) +// TODO: Need to encode possible double leap seconds, and negative leap seconds +static int64_t leap_seconds_after[] = { + // ls + (year + leap + day + thisleap) + (5*365+2+DEC31+0), // Dec 31 2005 + (8*365+2+DEC31+1), // Dec 31 2008 + (12*365+3+JUN30+1) // Jun 30 2012 +}; +static int n_leap_seconds_after = sizeof(leap_seconds_after)/sizeof(leap_seconds_after[0]); +#endif + +static int YearIsLeap(int year) { + return (year % 4 == 0) - (year % 100 == 0) + (year % 400 == 0); +} +static int DaysUntilYear(int year) { + return year*365 + (year/400) - (year/100) + (year/4); +} + +int64_t seconds_since_y2k(int years_since, int mon, int day, int h, int m, int s) +{ + errno = EINVAL; + if( !(1 <= mon && mon <= 12) ) return 0; + if( !(1 <= day && day <= DAYS_IN[mon-1]) ) return 0; + if( !(0 <= h && h <= 23) ) return 0; + if( !(0 <= m && m <= 59) ) return 0; + if( !(0 <= s && s <= 60) ) return 0; + + // Special case check for leap days + if( mon == 2 && day == 29 ) + { + if( !YearIsLeap(years_since) ) + return 0; + } + + // Day + int64_t days = DaysUntilYear(years_since); + days += DAYS_BEFORE[mon-1]; + if(mon > 2 && YearIsLeap(years_since)) + days ++; + days += day; + + // Seconds + int64_t seconds = h * 60*60 + m * 60; + seconds += s; + bool today_has_ls = false; + #if ENABLE_LEAP_SECONDS + if( days > 0 ) + { + for( int i = 0; i < n_leap_seconds_after; i ++ ) + { + if( days < leap_seconds_after[i] ) + break ; + if(days > leap_seconds_after[i]) + seconds ++; + else + today_has_ls = true; + // A leap second on this day is handled with s=60 + } + } + + // Now that we know if this day has a leap second, sanity check leap seconds + if( s == 60 ) + { + if( !today_has_ls || !(h == 23 && m == 59) ) + return 0; + } + #else + if( s == 60 ) return 0; + #endif + + errno = 0; + + return days * 24*60*60 + seconds; +} + +// returns number of days +int64_t get_days_since_y2k(int64_t ts, int *h, int *m, int *s) +{ + #if ENABLE_LEAP_SECONDS + // Calculate leap second count + int n_leap = 0; + bool is_ls = false; + if( ts > 0 ) + { + for( int i = 0; i < n_leap_seconds_after; i ++ ) + { + // lts = Timestamp of the leap second + int64_t lts = leap_seconds_after[i] * 24*60*60 + 23*60*60 + 59*60 + 60 + i; + if( lts > ts ) break; + if( lts == ts ) + is_ls = true; + n_leap ++; + } + } + ts -= n_leap; + #endif + + int64_t days = ts / 24*60*60; + int64_t seconds = ts % (24*60*60); + *s = (is_ls ? 60 : seconds % 60); + *m = (seconds/60 % 24); + *h = seconds / (60*60); + + return days; +} + +/** + * \param days Days since 1 Jan 2000 + */ +int64_t get_years_since_y2k(int64_t days, bool *is_leap, int *doy) +{ + // Calculate Year + bool is_ly = false; + // Year (400 yr blocks) - (400/4-3) leap years + const int days_per_400_yrs = 365*400 + (400/4-3); + int year = 400 * days / days_per_400_yrs; + days = days % days_per_400_yrs; + if( days < 366 ) // First year in 400 is a leap + is_ly = true; + else + { + // 100 yr blocks - 100/4-1 leap years + const int days_per_100_yrs = 365*100 + (100/4-1); + year += 100 * days / days_per_100_yrs; + days = days % days_per_100_yrs; + if( days < 366 ) // First year in 100 isn't a leap + is_ly = false; + else + { + const int days_per_4_yrs = 365*4 + 1; + year += 4 * days / days_per_4_yrs; + days = days % days_per_4_yrs; + if( days < 366 ) // First year in 4 is a leap + is_ly = true; + else { + year += days / 365; + days = days % 365; + } + } + } + *doy = days; + *is_leap = is_ly; + + return year; +} + +void get_month_day(int doy, bool is_ly, int *mon, int *day) +{ + if( doy > 365+(is_ly?1:0) ) { + *mon = 0; + *day = 0; + } + + bool mon_day_set = false; + if( doy >= DAYS_BEFORE[2] && is_ly ) + { + if( doy == DAYS_BEFORE[2] ) { + *mon = 2; + *day = 29; + mon_day_set = true; + } + doy --; + } + for( int i = 1; i < 12+1 && !mon_day_set; i ++ ) + { + if( doy < DAYS_BEFORE[i] ) + { + *mon = i; + *day = doy - DAYS_BEFORE[i]; + mon_day_set = true; + } + } +} + +int expand_from_secs_since_y2k(int64_t ts, int *years_since, int *mon, int *day, int *h, int *m, int *s) +{ + int64_t days = get_days_since_y2k(ts, h, m, s); + + bool is_ly; + int doy; + *years_since = get_years_since_y2k(days, &is_ly, &doy); + + // Calculate month/day of month + get_month_day(doy, is_ly, mon, day); + return 0; +} + diff --git a/Usermode/Libraries/libc.so_src/timeconv.h b/Usermode/Libraries/libc.so_src/timeconv.h new file mode 100644 index 00000000..1adba8f8 --- /dev/null +++ b/Usermode/Libraries/libc.so_src/timeconv.h @@ -0,0 +1,39 @@ +/* + * Acess2 C Library + * - By John Hodge (thePowersGang) + * + * timeconv.h + * - Shared User/Kernel time conversion code + */ +#ifndef _LIBC_TIMECONV_H_ +#define _LIBC_TIMECONV_H_ + +#include +#include + +extern int64_t seconds_since_y2k(int years_since, int mon, int day, int h, int m, int s); + +/** + * \return Number of days since Y2K + * + * Extracts the time of day from the timestamp, (possibly taking into account leap seconds) + */ +extern int64_t get_days_since_y2k(int64_t ts, int *h, int *m, int *s); + +/** + * \param days Number of days since Y2K + * \return Number of years since Y2K + * + * Converts a count of days since Y2K, and returns the number of years. Extracting the day of + * year, and if that year is a leap year. + */ +extern int64_t get_years_since_y2k(int64_t days, bool *is_leap, int *doy); + + +/** + * Gets the month and day of month from a day of year and leap year status + */ +extern void get_month_day(int doy, bool is_ly, int *mon, int *day); + +#endif +