diff options
Diffstat (limited to 'src/time')
-rw-r--r-- | src/time/CLOCKS_PER_SEC.c | 12 | ||||
-rw-r--r-- | src/time/NULL.ref | 3 | ||||
-rw-r--r-- | src/time/asctime.c | 36 | ||||
-rw-r--r-- | src/time/clock.c | 19 | ||||
-rw-r--r-- | src/time/clock_t.c | 13 | ||||
-rw-r--r-- | src/time/ctime.c | 18 | ||||
-rw-r--r-- | src/time/difftime.c | 17 | ||||
-rw-r--r-- | src/time/gmtime.c | 71 | ||||
-rw-r--r-- | src/time/localtime.c | 24 | ||||
-rw-r--r-- | src/time/mktime.c | 23 | ||||
-rw-r--r-- | src/time/size_t.ref | 3 | ||||
-rw-r--r-- | src/time/strftime.c | 187 | ||||
-rw-r--r-- | src/time/struct_tm.c | 23 | ||||
-rw-r--r-- | src/time/time.c | 31 | ||||
-rw-r--r-- | src/time/time_t.c | 14 |
15 files changed, 494 insertions, 0 deletions
diff --git a/src/time/CLOCKS_PER_SEC.c b/src/time/CLOCKS_PER_SEC.c new file mode 100644 index 00000000..7ef4bb89 --- /dev/null +++ b/src/time/CLOCKS_PER_SEC.c @@ -0,0 +1,12 @@ +#include <time.h> +#define CLOCKS_PER_SEC ((clock_t)1000000) + +/** clock ticks per second **/ + +/*** +is the number of clock ticks per second returned by FUNCTION(clock). +***/ + +/* +STDC(1) +*/ diff --git a/src/time/NULL.ref b/src/time/NULL.ref new file mode 100644 index 00000000..0ac4b016 --- /dev/null +++ b/src/time/NULL.ref @@ -0,0 +1,3 @@ +#include <time.h> +REFERENCE(stddef/NULL.c) +STDC(1) diff --git a/src/time/asctime.c b/src/time/asctime.c new file mode 100644 index 00000000..06dceae8 --- /dev/null +++ b/src/time/asctime.c @@ -0,0 +1,36 @@ +#include <time.h> +#include "stdio.h" + +/** convert broken down time to string **/ +char * asctime(const struct tm * timeptr) +{ + const char days[7][3] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + const char months[12][3] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + static char result[26]; + + sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", + days[timeptr->tm_wday], months[timeptr->tm_mon], + timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, + timeptr->tm_sec, timeptr->tm_year + 1900); + return result; +} + +/*** +converts the time specified at ARGUMENT(timeptr) to a string +in the format LITERAL(DDD MMM dd hh:mm:ss yyyy\n\0), where LITERAL(DDD) is the +three-character abbreviated day of the week, LITERAL(MMM) is the three-character +abbreviated month, LITERAL(dd) is the day of the month, LITERAL(hh) is the +hour of the day (in the range (0,23)), LITERAL(mm) is the minute of the hour +(in the range (0,59)), LITERAL(ss) is the second of the minute (in the range +(0,61)), and LITERAL(yyyy) is the year. +***/ + +/* +RETURN_ALWAYS(a pointer to the string) +STDC(1) +*/ diff --git a/src/time/clock.c b/src/time/clock.c new file mode 100644 index 00000000..a141e36d --- /dev/null +++ b/src/time/clock.c @@ -0,0 +1,19 @@ +#include <time.h> + +/** get processor time **/ +clock_t clock(void) +{ + return (clock_t)-1; +} + +/*** +returns the amount of processor time used by the current +program. To convert this time to seconds, divide it by CONSTANT(CLOCKS_PER_SEC). +***/ + +/* +IMPLEMENTATION(What constitutes CAST(TYPEDEF(clock_t), 0)) +RETURN_FAILURE(CAST(TYPEDEF(clock_t), -1)) +RETURN_SUCCESS(the processor time of the current program) +STDC(1) +*/ diff --git a/src/time/clock_t.c b/src/time/clock_t.c new file mode 100644 index 00000000..fe7a3842 --- /dev/null +++ b/src/time/clock_t.c @@ -0,0 +1,13 @@ +#include <time.h> +typedef long int clock_t; + +/** clock ticks **/ + +/*** +is an arithmetic type representing clock ticks. +***/ + +/* +DEFINED_TYPE(an arithmetic type) +STDC(1) +*/ diff --git a/src/time/ctime.c b/src/time/ctime.c new file mode 100644 index 00000000..5619e316 --- /dev/null +++ b/src/time/ctime.c @@ -0,0 +1,18 @@ +#include <time.h> + +/** convert arithmetic time to string **/ + +char * ctime(const time_t * timer) +{ + return asctime(localtime(timer)); +} + +/*** +converts the time at ARGUMENT(timer) to a string in the same format as +FUNCTION(asctime). +***/ + +/* +RETURN_ALWAYS(a pointer to the string) +STDC(1) +*/ diff --git a/src/time/difftime.c b/src/time/difftime.c new file mode 100644 index 00000000..17bb5c71 --- /dev/null +++ b/src/time/difftime.c @@ -0,0 +1,17 @@ +#include <time.h> + +/** find difference between two times **/ + +double difftime(time_t time1, time_t time0) +{ + return (double)time1 - (double)time0; +} + +/*** +subtracts ARGUMENT(time0) from ARGUMENT(time1). +***/ + +/* +RETURN_ALWAYS(the difference in seconds) +STDC(1) +*/ diff --git a/src/time/gmtime.c b/src/time/gmtime.c new file mode 100644 index 00000000..a844d097 --- /dev/null +++ b/src/time/gmtime.c @@ -0,0 +1,71 @@ +#include <time.h> +#include "nonstd/assert.h" + +# define SEC_PER_MIN (60L) +# define MIN_PER_HR (60L) +# define SEC_PER_HR ((SEC_PER_MIN) * (MIN_PER_HR)) +# define HR_PER_DAY (24L) +# define SEC_PER_DAY ((SEC_PER_HR) * (HR_PER_DAY)) +# define DAY_PER_YEAR (365L) /* not counting leap year */ +# define SEC_PER_YEAR ((SEC_PER_DAY) * (DAY_PER_YEAR)) +# define ISLEAPYEAR(y) ((y) % 4L == 0 && ((y) % 100L != 0 || (y) % 400L == 0)) +# define EPOCH_YEAR (70) + +/** convert arithmetic time to borken down time **/ + +struct tm * gmtime(const time_t * timer) +{ + static struct tm tm = {0}; + time_t seconds = 0; + int days = 0; + int days_per_mon[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + ASSERT_NONNULL(timer); + seconds = *timer; + + tm.tm_year = EPOCH_YEAR; + while (seconds > SEC_PER_YEAR) { + /* TODO: Will this mess up Dec 31 of leap year? */ + /* TODO: Or Jan 1 of year after leap year? */ + seconds -= SEC_PER_YEAR; + if (ISLEAPYEAR(tm.tm_year + 1900)) { + seconds -= SEC_PER_DAY; + } + tm.tm_year++; + } + if (ISLEAPYEAR(tm.tm_year + 1900)) { + days_per_mon[1] = 29; + } + + tm.tm_yday = (int)(seconds / SEC_PER_DAY); + seconds = seconds % SEC_PER_DAY; + tm.tm_hour = (int)(seconds / SEC_PER_HR); + seconds = seconds % SEC_PER_HR; + tm.tm_min = (int)(seconds / SEC_PER_MIN); + tm.tm_sec = (int)(seconds % SEC_PER_MIN); + + days = tm.tm_yday; + tm.tm_mon = 0; + while (days > days_per_mon[tm.tm_mon]) { + days -= days_per_mon[tm.tm_mon]; + tm.tm_mon++; + } + tm.tm_mday = days; + + /* TODO: tm_wday */ + tm.tm_wday = 0; + /* TODO: tm_isdst */ + tm.tm_isdst = 0; + + return &tm; +} + +/*** +converts the UTC time at ARGUMENT(timer) to a filled out STRUCTDEF(tm). +***/ + +/* +RETURN_FAILURE(CONSTANT(NULL)) +RETURN_SUCCESS(a pointer to the converted time) +STDC(1) +*/ diff --git a/src/time/localtime.c b/src/time/localtime.c new file mode 100644 index 00000000..b09f84a5 --- /dev/null +++ b/src/time/localtime.c @@ -0,0 +1,24 @@ +#include <time.h> +#include "nonstd/assert.h" + +/** convert arithmetic time to broken down time **/ + +struct tm * localtime(const time_t * timer) +{ + static struct tm tm = {0}; + ASSERT_NONNULL(timer); + + tm = *gmtime(timer); + /* TODO: adjust for timezone */ + + return &tm; +} + +/*** +converts the locale time at ARGUMENT(timer) to a filled out STRUCTDEF(tm). +***/ + +/* +RETURN_ALWAYS(a pointer to the converted object) +STDC(1) +*/ diff --git a/src/time/mktime.c b/src/time/mktime.c new file mode 100644 index 00000000..9e58d4eb --- /dev/null +++ b/src/time/mktime.c @@ -0,0 +1,23 @@ +#include <time.h> + +/** convert time structure to arithmetic type **/ + +time_t mktime(struct tm * timeptr) +{ + (void)timeptr; + return (time_t)-1; +} + +/*** +converts the local time pointed to by ARGUMENT(timeptr) to +an arithmetic value of type TYPEDEF(time_t). It also normalizes the values in +the STRUCTDEF(tm) at ARGUMENT(timeptr) to fit the defined limits, as well as +correcting the members MEMBER(tm_wday) and MEMBER(tm_yday) if they were +previously incorrect. +***/ + +/* +RETURN_FAILURE(CAST(TYPEDEF(time_t), -1)) +RETURN_SUCCESS(the converted time) +STDC(1) +*/ diff --git a/src/time/size_t.ref b/src/time/size_t.ref new file mode 100644 index 00000000..75ce0309 --- /dev/null +++ b/src/time/size_t.ref @@ -0,0 +1,3 @@ +#include <time.h> +REFERENCE(stddef/size_t.c) +STDC(1) diff --git a/src/time/strftime.c b/src/time/strftime.c new file mode 100644 index 00000000..abf56bc5 --- /dev/null +++ b/src/time/strftime.c @@ -0,0 +1,187 @@ +#include <time.h> +#include "stdio.h" +#include "nonstd/assert.h" +#include "nonstd/internal.h" +#include "locale.h" +#include "nonstd/locale.h" + +/** convert time to a formatted string **/ + +size_t strftime(char * restrict s, size_t maxsize, const char * restrict format, const struct tm * restrict timeptr) +{ + size_t converted = 0, i, j; + char buf[64]; + struct __locale_t *lc; + + ASSERT_NONNULL(s); + ASSERT_NONNULL(format); + ASSERT_NONNULL(timeptr); + + lc = __libc(THREAD_LOCALE); + + for (i = 0; format[i] != '\0' && converted < maxsize; i++) { + if (format[i] != '%') { + s[converted++] = format[i]; + continue; + } + + switch (format[++i]) { + case 'a': + sprintf(buf, "%s", lc->lc_time.abday[timeptr->tm_wday]); + break; + + case 'A': + sprintf(buf, "%s", lc->lc_time.day[timeptr->tm_wday]); + break; + + case 'b': + sprintf(buf, "%s", lc->lc_time.abmon[timeptr->tm_mon]); + break; + + case 'B': + sprintf(buf, "%s", lc->lc_time.mon[timeptr->tm_mon]); + break; + + case 'c': + /* FIXME: expand this */ + sprintf(buf, "%s", lc->lc_time.d_t_fmt); + break; + + case 'd': + sprintf(buf, "%02d", timeptr->tm_mday); + break; + + case 'H': + sprintf(buf, "%02d", timeptr->tm_hour); + break; + + case 'I': + sprintf(buf, "%02d", (timeptr->tm_hour + 1) % 13); + break; + + case 'j': + sprintf(buf, "%03d", timeptr->tm_yday + 1); + break; + + case 'm': + sprintf(buf, "%02d", timeptr->tm_mon + 1); + break; + + case 'M': + sprintf(buf, "%02d", timeptr->tm_min); + break; + + case 'p': + sprintf(buf, "%s", lc->lc_time.am_pm[timeptr->tm_hour < 12 ? 0 : 1]); + break; + + case 'S': + sprintf(buf, "%02d", timeptr->tm_sec); + break; + + case 'U': + /* TODO: two digit week of year, sunday based week */ + sprintf(buf, "%02d", timeptr->tm_yday / 7); + break; + + case 'w': + sprintf(buf, "%1d", timeptr->tm_wday); + break; + + case 'W': + /* TODO: two digit week of year, monday based week */ + sprintf(buf, "%02d", timeptr->tm_yday / 7); + break; + + case 'x': + /* TODO: expand this */ + sprintf(buf, "%s", lc->lc_time.d_fmt); + break; + + case 'X': + /* TODO: expand this */ + sprintf(buf, "%s", lc->lc_time.t_fmt); + break; + + case 'y': + sprintf(buf, "%02d", timeptr->tm_year % 100); + break; + + case 'Y': + sprintf(buf, "%d", timeptr->tm_year + 1900); + break; + + case 'Z': + sprintf(buf, "%s", "timezone"); + break; + + case '%': + sprintf(buf, "%%"); + break; + + default: + sprintf(buf, "UNDEFINED"); + /* undefined behavior */ + break; + } + + for (j = 0; buf[j] != '\0'; j++) { + s[converted++] = buf[j]; + if (converted >= maxsize - 1) { + break; + } + } + } + + s[converted++] = '\0'; + + if (converted >= maxsize) { + return 0; + } + + return converted; +} + +/*** +converts the time at ARGUMENT(timeptr) to a string of no more than +ARGUMENT(maxsize) bytes at ARGUMENT(s). The format of the converted string +is specified by ARGUMENT(format). The string at ARGUMENT(format) may contain +conversion specifiers, which consist of a CHAR(%) followed by one character. +All other characters are copied to ARGUMENT(s) verbatim. + +The conversion specifiers are: + +FLAG(%a, the current locales abbreviated weekday name) +FLAG(%A, the current locales full weekday name) +FLAG(%b, the current locales abbreviated month name) +FLAG(%B, the current locales full month name) +FLAG(%c, the current locales date and time representation) +FLAG(%d, the day of the month (in the range (01,31))) +FLAG(%H, the hour (in the range (00,23))) +FLAG(%I, the hour (in the range (01,12))) +FLAG(%j, the day of the year (in the range (001,366))) +FLAG(%m, the numeric month (in the range (01,12))) +FLAG(%M, the minute (in the range (00,59))) +FLAG(%p, the current locales AM/PM designator) +FLAG(%S, the second (in the range (00,61))) +FLAG(%U, the week of the year (Sunday based, in the range (00,53))) +FLAG(%w, the numeric weekday (in the range (0,6), with Sunday as 0)) +FLAG(%W, the week of the year (Monday based, in the range (00,53))) +FLAG(%x, the current locales date representation) +FLAG(%X, the current locales time representation) +FLAG(%y, the year without centruy (in the range (00,99))) +FLAG(%Y, the year with century) +FLAG(%Z, the time zone name or abbreviation, if determinable) +FLAG(%%, a literal %) +***/ + +/* +UNDEFINED(Copying takes place between objects that overlap) +LC_TIME +RETURN_FAILURE(ZERO) +RETURN_SUCCESS(the length of the converted string, not counting the terminating null) +*/ + +/* +STDC(1) +*/ diff --git a/src/time/struct_tm.c b/src/time/struct_tm.c new file mode 100644 index 00000000..067d54f3 --- /dev/null +++ b/src/time/struct_tm.c @@ -0,0 +1,23 @@ +#include <time.h> + +/** broken-down time **/ + +struct tm { + int tm_sec; /* Seconds [0,60] */ + int tm_min; /* Minutes [0, 59] */ + int tm_hour; /* Hour [0,23] */ + int tm_mday; /* Day of the month [1,31] */ + int tm_mon; /* Month of the year [0,11] */ + int tm_year; /* Years since 1900 */ + int tm_wday; /* Day of the week [0,6] (Sunday = 0) */ + int tm_yday; /* Day of the year [0,365] */ + int tm_isdst; /* Daylight Saving Time flag */ +}; + +/*** +is used to represent time broken down into its individual components. +***/ + +/* +STDC(1) +*/ diff --git a/src/time/time.c b/src/time/time.c new file mode 100644 index 00000000..abe47471 --- /dev/null +++ b/src/time/time.c @@ -0,0 +1,31 @@ +#include <time.h> +#include "nonstd/internal.h" +#include "nonstd/syscall.h" + +/** get current time **/ + +time_t time(time_t * timer) +{ + long int now; + SYSCALL_NUMBER(sc, "time", 0); + + now = __syscall(sc); + + if (timer != NULL && now != -1) { + *timer = (time_t)now; + } + + return (time_t)now; +} + +/*** +gets the current time. If ARGUMENT(timer) is not CONSTANT(NULL), +the current time is also stored in the object it points to. +***/ + +/* +UNSPECIFIED(The encoding of TYPEDEF(time_t)) +RETURN_FAILURE(CAST(TYPEDEF(time_t), -1)) +RETURN_SUCCESS(the current calndar time) +STDC(1) +*/ diff --git a/src/time/time_t.c b/src/time/time_t.c new file mode 100644 index 00000000..df2f34e8 --- /dev/null +++ b/src/time/time_t.c @@ -0,0 +1,14 @@ +#include <time.h> + +/** time representation **/ + +typedef long int time_t; + +/*** +is used for representing time. +***/ + +/* +DEFINED_TYPE(an arithmetic type) +STDC(1) +*/ |