Usermode/libc - C++ wrapping in headers, time rework
authorJohn Hodge <[email protected]>
Sat, 8 Mar 2014 06:01:35 +0000 (14:01 +0800)
committerJohn Hodge <[email protected]>
Sat, 8 Mar 2014 06:01:35 +0000 (14:01 +0800)
17 files changed:
Usermode/Libraries/libc.so_src/Makefile
Usermode/Libraries/libc.so_src/ctype.c [new file with mode: 0644]
Usermode/Libraries/libc.so_src/errno.c
Usermode/Libraries/libc.so_src/include_exp/assert.h
Usermode/Libraries/libc.so_src/include_exp/ctype.h
Usermode/Libraries/libc.so_src/include_exp/errno.enum.h
Usermode/Libraries/libc.so_src/include_exp/setjmp.h
Usermode/Libraries/libc.so_src/include_exp/signal.h
Usermode/Libraries/libc.so_src/include_exp/stdio.h
Usermode/Libraries/libc.so_src/include_exp/stdlib.h
Usermode/Libraries/libc.so_src/include_exp/string.h
Usermode/Libraries/libc.so_src/include_exp/time.h
Usermode/Libraries/libc.so_src/stdio.c
Usermode/Libraries/libc.so_src/string.c
Usermode/Libraries/libc.so_src/time.c
Usermode/Libraries/libc.so_src/timeconv.c [new file with mode: 0644]
Usermode/Libraries/libc.so_src/timeconv.h [new file with mode: 0644]

index 4c37d18..3c18c28 100644 (file)
@@ -12,7 +12,7 @@ INCFILES := stdio.h stdlib.h
 \r
 OBJ  = stub.o heap.o stdlib.o env.o stdio.o string.o rand.o\r
 OBJ += scanf.o signals.o strtoi.o strtof.o\r
-OBJ += printf.o time.o errno.o\r
+OBJ += printf.o time.o timeconv.o errno.o ctype.o\r
 OBJ += arch/$(ARCHDIR).ao\r
 # signals.o\r
 DEPFILES := $(OBJ:%.o=%.d)\r
diff --git a/Usermode/Libraries/libc.so_src/ctype.c b/Usermode/Libraries/libc.so_src/ctype.c
new file mode 100644 (file)
index 0000000..d5a5e97
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Acess2 C Library
+ * - By John Hodge (thePowersGang)
+ *
+ * ctype.c
+ * - Character Types
+ */
+#include <ctype.h>
+
+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;
+}
+
index e2948d6..6f95457 100644 (file)
@@ -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";
index dde4aee..d7029e5 100644 (file)
@@ -8,6 +8,10 @@
 #ifndef _LIBC__ASSERT_H_
 #define _LIBC__ASSERT_H_
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #include <stdlib.h>
 //#include <stdio.h>
 #include <acess/sys.h>
@@ -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
 
index 60753a6..75e4ce8 100644 (file)
@@ -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
index 6d33bd4..f943654 100755 (executable)
@@ -27,6 +27,8 @@ enum libc_eErrorNumbers {
 
        EAGAIN, // Try again
        EALREADY,       // Operation was a NOP
+       
+       EFBIG,  // File too large
 
        // psockets
        EAFNOSUPPORT,   
index fe545af..5eb7bb5 100644 (file)
@@ -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
 
index a4c8bd3..38de258 100644 (file)
@@ -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
 
index 4d812a7..ed1fce5 100644 (file)
@@ -9,6 +9,10 @@
 #include <stdarg.h>
 #include <stddef.h>    // 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
 
index 7169150..07fc81f 100644 (file)
@@ -9,6 +9,10 @@
 #include <stdarg.h>\r
 #include <sys/types.h>\r
 \r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
 #define EXIT_FAILURE   1\r
 #define EXIT_SUCCESS   0\r
 \r
@@ -31,6 +35,8 @@
 # define labs  acess_labs\r
 # define llabs acess_llabs\r
 \r
+# define mktemp        acess_mktemp\r
+\r
 # define getenv        acess_getenv\r
 # define putenv        acess_putenv\r
 \r
@@ -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);\r
 extern unsigned long   strtoul(const char *ptr, char **end, int base);\r
 extern int     atoi(const char *ptr);\r
+extern long    atol(const char *ptr);\r
+extern long long       atoll(const char *ptr);\r
 \r
 extern double  strtod(const char *ptr, char **end);\r
 extern float   strtof(const char *ptr, char **end);\r
@@ -74,6 +82,8 @@ extern int    abs(int j);
 extern long int        labs(long int j);\r
 extern long long int   llabs(long long int j);\r
 \r
+extern char    *mktemp(char *__template);\r
+\r
 /* --- Environment --- */\r
 extern char    *getenv(const char *name);\r
 extern int     putenv(char *string);\r
@@ -102,4 +112,10 @@ extern int rand_p(unsigned int *seedp);
 # define SEEK_END      (-1)\r
 #endif\r
 \r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#include <libposix_stdlib.h>\r
+\r
 #endif\r
index 493d5ef..7ef1bc7 100644 (file)
@@ -7,6 +7,10 @@
 
 #include <stddef.h>
 
+#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
index 8480d68..4c8d3ea 100644 (file)
 #include <sys/types.h> // time_t
 #include <stddef.h>    // 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 <libposix_time.h>
 
index e98ca42..a944f9b 100644 (file)
@@ -223,6 +223,33 @@ EXPORT FILE *open_memstream(char **bufferptr, size_t *lengthptr)
        return ret;\r
 }\r
 \r
+EXPORT FILE *fdopen(int fd, const char *mode)\r
+{\r
+       FILE    *ret;\r
+       \r
+       if( fd < 0 || !mode )   return NULL;\r
+       \r
+       ret = get_file_struct();\r
+       \r
+       ret->FD = fd;\r
+       ret->Flags = _fopen_modetoflags(mode);\r
+       if(ret->Flags == -1) {\r
+               ret->Flags = 0;\r
+               return NULL;\r
+       }\r
+       \r
+       ret->Buffer = NULL;\r
+       ret->BufferPos = 0;\r
+       ret->BufferSpace = 0;\r
+       \r
+       return ret;\r
+}\r
+\r
+EXPORT FILE *tmpfile(void)\r
+{\r
+       return NULL;\r
+}\r
+\r
 EXPORT int fclose(FILE *fp)\r
 {\r
        if( !(fp->Flags & FILE_FLAG_ALLOC) )\r
@@ -452,7 +479,7 @@ int _fseek_memstream(FILE *fp, long int amt, int whence)
        return 0;\r
 }\r
 \r
-EXPORT int fseek(FILE *fp, long int amt, int whence)\r
+EXPORT int fseeko(FILE *fp, off_t amt, int whence)\r
 {\r
        if(!fp || fp->FD == FD_NOTOPEN) {\r
                errno = EBADF;\r
@@ -473,6 +500,11 @@ EXPORT int fseek(FILE *fp, long int amt, int whence)
        }\r
 }\r
 \r
+EXPORT int fseek(FILE *fp, long int amt, int whence)\r
+{\r
+       return fseeko(fp, amt, whence);\r
+}\r
+\r
 size_t _fwrite_unbuffered(FILE *fp, size_t size, size_t num, const void *data)\r
 {\r
        size_t  ret = 0, bytes;\r
index 6ee6d6c..aa79ec9 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdio.h>
 #include <ctype.h>
 #include "lib.h"
+#include <string.h>
 
 /**
  * \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;
+}
+
index 412475b..330b6a7 100644 (file)
@@ -8,12 +8,34 @@
 #include <time.h>
 #include <acess/sys.h>
 #include <string.h>
+#include "timeconv.h"
+#include <errno.h>
+
+#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 (file)
index 0000000..6fed585
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Acess2 C Library
+ * - By John Hodge (thePowersGang)
+ *
+ * timeconv.c
+ * - Shared User/Kernel time conversion code
+ */
+#include "timeconv.h"
+#include <errno.h>
+
+#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 (file)
index 0000000..1adba8f
--- /dev/null
@@ -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 <stdint.h>
+#include <stdbool.h>
+
+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
+

UCC git Repository :: git.ucc.asn.au