summaryrefslogtreecommitdiff
path: root/src/time
diff options
context:
space:
mode:
Diffstat (limited to 'src/time')
-rw-r--r--src/time/CLOCKS_PER_SEC.c12
-rw-r--r--src/time/NULL.ref3
-rw-r--r--src/time/asctime.c36
-rw-r--r--src/time/clock.c19
-rw-r--r--src/time/clock_t.c13
-rw-r--r--src/time/ctime.c18
-rw-r--r--src/time/difftime.c17
-rw-r--r--src/time/gmtime.c71
-rw-r--r--src/time/localtime.c24
-rw-r--r--src/time/mktime.c23
-rw-r--r--src/time/size_t.ref3
-rw-r--r--src/time/strftime.c187
-rw-r--r--src/time/struct_tm.c23
-rw-r--r--src/time/time.c31
-rw-r--r--src/time/time_t.c14
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)
+*/