summaryrefslogtreecommitdiff
path: root/libc/time
diff options
context:
space:
mode:
Diffstat (limited to 'libc/time')
-rw-r--r--libc/time/asctime.c64
-rw-r--r--libc/time/asctime_r.c27
-rw-r--r--libc/time/clock.c69
-rw-r--r--libc/time/ctime.c52
-rw-r--r--libc/time/ctime_r.c15
-rw-r--r--libc/time/difftime.c44
-rw-r--r--libc/time/gmtime.c67
-rw-r--r--libc/time/gmtime_r.c17
-rw-r--r--libc/time/lcltime.c57
-rw-r--r--libc/time/lcltime_r.c104
-rw-r--r--libc/time/mktime.c204
-rw-r--r--libc/time/strftime.c444
-rw-r--r--libc/time/time.c59
13 files changed, 1223 insertions, 0 deletions
diff --git a/libc/time/asctime.c b/libc/time/asctime.c
new file mode 100644
index 0000000..4ad35e8
--- /dev/null
+++ b/libc/time/asctime.c
@@ -0,0 +1,64 @@
+/*
+ * asctime.c
+ * Original Author: G. Haley
+ *
+ * Converts the broken down time in the structure pointed to by tim_p into a
+ * string of the form
+ *
+ * Wed Jun 15 11:38:07 1988\n\0
+ *
+ * Returns a pointer to the string.
+ */
+
+/*
+FUNCTION
+<<asctime>>---format time as string
+
+INDEX
+ asctime
+INDEX
+ _asctime_r
+
+ANSI_SYNOPSIS
+ #include <time.h>
+ char *asctime(const struct tm *<[clock]>);
+ char *asctime_r(const struct tm *<[clock]>, char *<[buf]>);
+
+TRAD_SYNOPSIS
+ #include <time.h>
+ char *asctime(<[clock]>)
+ struct tm *<[clock]>;
+ char *asctime_r(<[clock]>)
+ struct tm *<[clock]>;
+ char *<[buf]>;
+
+DESCRIPTION
+Format the time value at <[clock]> into a string of the form
+. Wed Jun 15 11:38:07 1988\n\0
+The string is generated in a static buffer; each call to <<asctime>>
+overwrites the string generated by previous calls.
+
+RETURNS
+A pointer to the string containing a formatted timestamp.
+
+PORTABILITY
+ANSI C requires <<asctime>>.
+
+<<asctime>> requires no supporting OS subroutines.
+*/
+
+#include <time.h>
+#include <_ansi.h>
+#include <reent.h>
+
+#ifndef _REENT_ONLY
+
+char *
+_DEFUN (asctime, (tim_p),
+ _CONST struct tm *tim_p)
+{
+ char *buf = _REENT->_new._reent._asctime_buf;
+ return asctime_r (tim_p, buf);
+}
+
+#endif
diff --git a/libc/time/asctime_r.c b/libc/time/asctime_r.c
new file mode 100644
index 0000000..ff70ea4
--- /dev/null
+++ b/libc/time/asctime_r.c
@@ -0,0 +1,27 @@
+/*
+ * asctime_r.c
+ */
+
+#include <stdio.h>
+#include <time.h>
+
+char *
+_DEFUN (asctime_r, (tim_p, result),
+ _CONST struct tm *tim_p _AND
+ char *result)
+{
+ static _CONST char day_name[7][3] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+ };
+ static _CONST char mon_name[12][3] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+
+ sprintf (result, "%.3s %.3s %.2d %.2d:%.2d:%.2d %d\n",
+ day_name[tim_p->tm_wday],
+ mon_name[tim_p->tm_mon],
+ tim_p->tm_mday, tim_p->tm_hour, tim_p->tm_min,
+ tim_p->tm_sec, 1900 + tim_p->tm_year);
+ return result;
+}
diff --git a/libc/time/clock.c b/libc/time/clock.c
new file mode 100644
index 0000000..b15915d
--- /dev/null
+++ b/libc/time/clock.c
@@ -0,0 +1,69 @@
+/* NetWare can not use this implementation of clock, since it does not
+ have times or any similar function. It provides its own version of
+ clock in clib.nlm. If we can not use clib.nlm, then we must write
+ clock in sys/netware. */
+
+#ifdef CLOCK_PROVIDED
+
+int _dummy_clock = 1;
+
+#else
+
+/*
+ * clock.c
+ * Original Author: G. Haley
+ *
+ * Determines the processor time used by the program since invocation. The time
+ * in seconds is the value returned divided by the value of the macro CLK_TCK.
+ * If the processor time used is not available, (clock_t) -1 is returned.
+ */
+
+/*
+FUNCTION
+<<clock>>---cumulative processor time
+
+INDEX
+ clock
+
+ANSI_SYNOPSIS
+ #include <time.h>
+ clock_t clock(void);
+
+TRAD_SYNOPSIS
+ #include <time.h>
+ clock_t clock();
+
+DESCRIPTION
+Calculates the best available approximation of the cumulative amount
+of time used by your program since it started. To convert the result
+into seconds, divide by the macro <<CLOCKS_PER_SEC>>.
+
+RETURNS
+The amount of processor time used so far by your program, in units
+defined by the machine-dependent macro <<CLOCKS_PER_SEC>>. If no
+measurement is available, the result is <<-1>>.
+
+PORTABILITY
+ANSI C requires <<clock>> and <<CLOCKS_PER_SEC>>.
+
+Supporting OS subroutine required: <<times>>.
+*/
+
+#include <time.h>
+#include <sys/times.h>
+#include <reent.h>
+
+clock_t
+clock ()
+{
+ struct tms tim_s;
+ clock_t res;
+
+ if ((res = (clock_t) _times_r (_REENT, &tim_s)) != -1)
+ res = (clock_t) (tim_s.tms_utime + tim_s.tms_stime +
+ tim_s.tms_cutime + tim_s.tms_cstime);
+
+ return res;
+}
+
+#endif /* CLOCK_PROVIDED */
diff --git a/libc/time/ctime.c b/libc/time/ctime.c
new file mode 100644
index 0000000..e8ccc14
--- /dev/null
+++ b/libc/time/ctime.c
@@ -0,0 +1,52 @@
+/*
+ * ctime.c
+ * Original Author: G. Haley
+ */
+
+/*
+FUNCTION
+<<ctime>>---convert time to local and format as string
+
+INDEX
+ ctime
+
+ANSI_SYNOPSIS
+ #include <time.h>
+ char *ctime(time_t <[clock]>);
+ char *ctime_r(time_t <[clock]>, char *<[buf]>);
+
+TRAD_SYNOPSIS
+ #include <time.h>
+ char *ctime(<[clock]>)
+ time_t <[clock]>;
+ char *ctime_r(<[clock]>, <[buf]>)
+ time_t <[clock]>;
+ char *<[buf]>;
+
+DESCRIPTION
+Convert the time value at <[clock]> to local time (like <<localtime>>)
+and format it into a string of the form
+. Wed Jun 15 11:38:07 1988\n\0
+(like <<asctime>>).
+
+RETURNS
+A pointer to the string containing a formatted timestamp.
+
+PORTABILITY
+ANSI C requires <<ctime>>.
+
+<<ctime>> requires no supporting OS subroutines.
+*/
+
+#include <time.h>
+
+#ifndef _REENT_ONLY
+
+char *
+_DEFUN (ctime, (tim_p),
+ _CONST time_t * tim_p)
+{
+ return asctime (localtime (tim_p));
+}
+
+#endif
diff --git a/libc/time/ctime_r.c b/libc/time/ctime_r.c
new file mode 100644
index 0000000..fda8cac
--- /dev/null
+++ b/libc/time/ctime_r.c
@@ -0,0 +1,15 @@
+/*
+ * ctime_r.c
+ */
+
+#include <time.h>
+
+char *
+_DEFUN (ctime_r, (tim_p, result),
+ _CONST time_t * tim_p _AND
+ char * result)
+
+{
+ struct tm tm;
+ return asctime_r (localtime_r (tim_p, &tm), result);
+}
diff --git a/libc/time/difftime.c b/libc/time/difftime.c
new file mode 100644
index 0000000..93a4f00
--- /dev/null
+++ b/libc/time/difftime.c
@@ -0,0 +1,44 @@
+/*
+ * difftime.c
+ * Original Author: G. Haley
+ */
+
+/*
+FUNCTION
+<<difftime>>---subtract two times
+
+INDEX
+ difftime
+
+ANSI_SYNOPSIS
+ #include <time.h>
+ double difftime(time_t <[tim1]>, time_t <[tim2]>);
+
+TRAD_SYNOPSIS
+ #include <time.h>
+ double difftime(<[tim1]>, <[tim2]>)
+ time_t <[tim1]>;
+ time_t <[tim2]>;
+
+DESCRIPTION
+Subtracts the two times in the arguments: `<<<[tim1]> - <[tim2]>>>'.
+
+RETURNS
+The difference (in seconds) between <[tim2]> and <[tim1]>, as a <<double>>.
+
+PORTABILITY
+ANSI C requires <<difftime>>, and defines its result to be in seconds
+in all implementations.
+
+<<difftime>> requires no supporting OS subroutines.
+*/
+
+#include <time.h>
+
+double
+_DEFUN (difftime, (tim1, tim2),
+ time_t tim1 _AND
+ time_t tim2)
+{
+ return ((double) tim1 - tim2);
+}
diff --git a/libc/time/gmtime.c b/libc/time/gmtime.c
new file mode 100644
index 0000000..4f5bbe4
--- /dev/null
+++ b/libc/time/gmtime.c
@@ -0,0 +1,67 @@
+/*
+ * gmtime.c
+ * Original Author: G. Haley
+ *
+ * Converts the calendar time pointed to by tim_p into a broken-down time
+ * expressed as Greenwich Mean Time (GMT). Returns a pointer to a structure
+ * containing the broken-down time, or a null pointer if GMT is not
+ * available.
+ */
+
+/*
+FUNCTION
+<<gmtime>>---convert time to UTC traditional form
+
+INDEX
+ gmtime
+
+ANSI_SYNOPSIS
+ #include <time.h>
+ struct tm *gmtime(const time_t *<[clock]>);
+ struct tm *gmtime_r(const time_t *<[clock]>, struct tm *<[res]>);
+
+TRAD_SYNOPSIS
+ #include <time.h>
+ struct tm *gmtime(<[clock]>)
+ const time_t *<[clock]>;
+ struct tm *gmtime_r(<[clock]>, <[res]>)
+ const time_t *<[clock]>;
+ struct tm *<[res]>;
+
+DESCRIPTION
+<<gmtime>> assumes the time at <[clock]> represents a local time.
+<<gmtime>> converts it to UTC (Universal Coordinated Time, also known in some
+countries as GMT, Greenwich Mean time), then converts the
+representation from the arithmetic representation to
+the traditional representation defined by <<struct tm>>.
+
+<<gmtime>> constructs the traditional time representation in static
+storage; each call to <<gmtime>> or <<localtime>> will overwrite the
+information generated by previous calls to either function.
+
+RETURNS
+A pointer to the traditional time representation (<<struct tm>>).
+
+PORTABILITY
+ANSI C requires <<gmtime>>.
+
+<<gmtime>> requires no supporting OS subroutines.
+*/
+
+#include <stdlib.h>
+#include <time.h>
+
+#define _GMT_OFFSET 0
+
+#ifndef _REENT_ONLY
+
+struct tm *
+_DEFUN (gmtime, (tim_p),
+ _CONST time_t * tim_p)
+{
+ time_t tim = *tim_p + _GMT_OFFSET;
+
+ return (localtime (&tim));
+}
+
+#endif
diff --git a/libc/time/gmtime_r.c b/libc/time/gmtime_r.c
new file mode 100644
index 0000000..7afa021
--- /dev/null
+++ b/libc/time/gmtime_r.c
@@ -0,0 +1,17 @@
+/*
+ * gmtime_r.c
+ */
+
+#include <time.h>
+
+#define _GMT_OFFSET 0
+
+struct tm *
+_DEFUN (gmtime_r, (tim_p, res),
+ _CONST time_t * tim_p _AND
+ struct tm *res)
+{
+ time_t tim = *tim_p + _GMT_OFFSET;
+
+ return (localtime_r (&tim, res));
+}
diff --git a/libc/time/lcltime.c b/libc/time/lcltime.c
new file mode 100644
index 0000000..d4c7d7d
--- /dev/null
+++ b/libc/time/lcltime.c
@@ -0,0 +1,57 @@
+/*
+ * localtime.c
+ */
+
+/*
+FUNCTION
+<<localtime>>---convert time to local representation
+
+INDEX
+ localtime
+
+ANSI_SYNOPSIS
+ #include <time.h>
+ struct tm *localtime(time_t *<[clock]>);
+ struct tm *localtime_r(time_t *<[clock]>, struct tm *<[res]>);
+
+TRAD_SYNOPSIS
+ #include <time.h>
+ struct tm *localtime(<[clock]>)
+ time_t *<[clock]>;
+ struct tm *localtime(<[clock]>, <[res]>)
+ time_t *<[clock]>;
+ struct tm *<[res]>;
+
+DESCRIPTION
+<<localtime>> converts the time at <[clock]> into local time, then
+converts its representation from the arithmetic representation to the
+traditional representation defined by <<struct tm>>.
+
+<<localtime>> constructs the traditional time representation in static
+storage; each call to <<gmtime>> or <<localtime>> will overwrite the
+information generated by previous calls to either function.
+
+<<mktime>> is the inverse of <<localtime>>.
+
+RETURNS
+A pointer to the traditional time representation (<<struct tm>>).
+
+PORTABILITY
+ANSI C requires <<localtime>>.
+
+<<localtime>> requires no supporting OS subroutines.
+*/
+
+#include <time.h>
+#include <reent.h>
+
+#ifndef _REENT_ONLY
+
+struct tm *
+_DEFUN (localtime, (tim_p),
+ _CONST time_t * tim_p)
+{
+ return localtime_r (tim_p, &(_REENT->_new._reent._localtime_buf));
+}
+
+#endif
diff --git a/libc/time/lcltime_r.c b/libc/time/lcltime_r.c
new file mode 100644
index 0000000..1b4269e
--- /dev/null
+++ b/libc/time/lcltime_r.c
@@ -0,0 +1,104 @@
+/*
+ * localtime_r.c
+ * Original Author: Adapted from tzcode maintained by Arthur David Olson.
+ *
+ * Converts the calendar time pointed to by tim_p into a broken-down time
+ * expressed as local time. Returns a pointer to a structure containing the
+ * broken-down time.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+
+#define SECSPERMIN 60L
+#define MINSPERHOUR 60L
+#define HOURSPERDAY 24L
+#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
+#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY)
+#define DAYSPERWEEK 7
+#define MONSPERYEAR 12
+
+#define YEAR_BASE 1900
+#define EPOCH_YEAR 1970
+#define EPOCH_WDAY 4
+
+#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+
+static _CONST int mon_lengths[2][MONSPERYEAR] = {
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
+} ;
+
+static _CONST int year_lengths[2] = {
+ 365,
+ 366
+} ;
+
+struct tm *
+_DEFUN (localtime_r, (tim_p, res),
+ _CONST time_t * tim_p _AND
+ struct tm *res)
+{
+ long days, rem;
+ int y;
+ int yleap;
+ _CONST int *ip;
+
+ days = ((long) *tim_p) / SECSPERDAY;
+ rem = ((long) *tim_p) % SECSPERDAY;
+ while (rem < 0)
+ {
+ rem += SECSPERDAY;
+ --days;
+ }
+ while (rem >= SECSPERDAY)
+ {
+ rem -= SECSPERDAY;
+ ++days;
+ }
+
+ /* compute hour, min, and sec */
+ res->tm_hour = (int) (rem / SECSPERHOUR);
+ rem %= SECSPERHOUR;
+ res->tm_min = (int) (rem / SECSPERMIN);
+ res->tm_sec = (int) (rem % SECSPERMIN);
+
+ /* compute day of week */
+ if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0)
+ res->tm_wday += DAYSPERWEEK;
+
+ /* compute year & day of year */
+ y = EPOCH_YEAR;
+ if (days >= 0)
+ {
+ for (;;)
+ {
+ yleap = isleap(y);
+ if (days < year_lengths[yleap])
+ break;
+ y++;
+ days -= year_lengths[yleap];
+ }
+ }
+ else
+ {
+ do
+ {
+ --y;
+ yleap = isleap(y);
+ days += year_lengths[yleap];
+ } while (days < 0);
+ }
+
+ res->tm_year = y - YEAR_BASE;
+ res->tm_yday = days;
+ ip = mon_lengths[yleap];
+ for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon)
+ days -= ip[res->tm_mon];
+ res->tm_mday = days + 1;
+
+ /* set daylight saving time flag */
+ res->tm_isdst = -1;
+
+ return (res);
+}
diff --git a/libc/time/mktime.c b/libc/time/mktime.c
new file mode 100644
index 0000000..431eca5
--- /dev/null
+++ b/libc/time/mktime.c
@@ -0,0 +1,204 @@
+/*
+ * mktime.c
+ * Original Author: G. Haley
+ *
+ * Converts the broken-down time, expressed as local time, in the structure
+ * pointed to by tim_p into a calendar time value. The original values of the
+ * tm_wday and tm_yday fields of the structure are ignored, and the original
+ * values of the other fields have no restrictions. On successful completion
+ * the fields of the structure are set to represent the specified calendar
+ * time. Returns the specified calendar time. If the calendar time can not be
+ * represented, returns the value (time_t) -1.
+ */
+
+/*
+FUNCTION
+<<mktime>>---convert time to arithmetic representation
+
+INDEX
+ mktime
+
+ANSI_SYNOPSIS
+ #include <time.h>
+ time_t mktime(struct tm *<[timp]>);
+
+TRAD_SYNOPSIS
+ #include <time.h>
+ time_t mktime(<[timp]>)
+ struct tm *<[timp]>;
+
+DESCRIPTION
+<<mktime>> assumes the time at <[timp]> is a local time, and converts
+its representation from the traditional representation defined by
+<<struct tm>> into a representation suitable for arithmetic.
+
+<<localtime>> is the inverse of <<mktime>>.
+
+RETURNS
+If the contents of the structure at <[timp]> do not form a valid
+calendar time representation, the result is <<-1>>. Otherwise, the
+result is the time, converted to a <<time_t>> value.
+
+PORTABILITY
+ANSI C requires <<mktime>>.
+
+<<mktime>> requires no supporting OS subroutines.
+*/
+
+#include <stdlib.h>
+#include <time.h>
+
+#define _SEC_IN_MINUTE 60
+#define _SEC_IN_HOUR 3600
+#define _SEC_IN_DAY 86400
+
+static _CONST int DAYS_IN_MONTH[12] =
+{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+#define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x])
+
+static _CONST int _DAYS_BEFORE_MONTH[12] =
+{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+#define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || (((y)+1900) % 400) == 0))
+#define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365)
+
+static void
+validate_structure (tim_p)
+ struct tm *tim_p;
+{
+ div_t res;
+ int days_in_feb = 28;
+
+ /* calculate time & date to account for out of range values */
+ if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59)
+ {
+ res = div (tim_p->tm_sec, 60);
+ tim_p->tm_min += res.quot;
+ if ((tim_p->tm_sec = res.rem) < 0)
+ {
+ tim_p->tm_sec += 60;
+ --tim_p->tm_min;
+ }
+ }
+
+ if (tim_p->tm_min < 0 || tim_p->tm_min > 59)
+ {
+ res = div (tim_p->tm_min, 60);
+ tim_p->tm_hour += res.quot;
+ if ((tim_p->tm_min = res.rem) < 0)
+ {
+ tim_p->tm_min += 60;
+ --tim_p->tm_hour;
+ }
+ }
+
+ if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23)
+ {
+ res = div (tim_p->tm_hour, 24);
+ tim_p->tm_mday += res.quot;
+ if ((tim_p->tm_hour = res.rem) < 0)
+ {
+ tim_p->tm_hour += 24;
+ --tim_p->tm_mday;
+ }
+ }
+
+ if (tim_p->tm_mon > 11)
+ {
+ res = div (tim_p->tm_mon, 12);
+ tim_p->tm_year += res.quot;
+ if ((tim_p->tm_mon = res.rem) < 0)
+ {
+ tim_p->tm_mon += 12;
+ --tim_p->tm_year;
+ }
+ }
+
+ if (_DAYS_IN_YEAR (tim_p->tm_year) == 366)
+ days_in_feb = 29;
+
+ if (tim_p->tm_mday <= 0)
+ {
+ while (tim_p->tm_mday <= 0)
+ {
+ if (--tim_p->tm_mon == -1)
+ {
+ tim_p->tm_year--;
+ tim_p->tm_mon = 11;
+ days_in_feb =
+ ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
+ 29 : 28);
+ }
+ tim_p->tm_mday += _DAYS_IN_MONTH (tim_p->tm_mon);
+ }
+ }
+ else
+ {
+ while (tim_p->tm_mday > _DAYS_IN_MONTH (tim_p->tm_mon))
+ {
+ tim_p->tm_mday -= _DAYS_IN_MONTH (tim_p->tm_mon);
+ if (++tim_p->tm_mon == 12)
+ {
+ tim_p->tm_year++;
+ tim_p->tm_mon = 0;
+ days_in_feb =
+ ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ?
+ 29 : 28);
+ }
+ }
+ }
+}
+
+time_t
+mktime (tim_p)
+ struct tm *tim_p;
+{
+ time_t tim = 0;
+ long days = 0;
+ int year;
+
+ /* validate structure */
+ validate_structure (tim_p);
+
+ /* compute hours, minutes, seconds */
+ tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE) +
+ (tim_p->tm_hour * _SEC_IN_HOUR);
+
+ /* compute days in year */
+ days += tim_p->tm_mday - 1;
+ days += _DAYS_BEFORE_MONTH[tim_p->tm_mon];
+ if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366)
+ days++;
+
+ /* compute day of the year */
+ tim_p->tm_yday = days;
+
+ if (tim_p->tm_year > 10000
+ || tim_p->tm_year < -10000)
+ {
+ return (time_t) -1;
+ }
+
+ /* compute days in other years */
+ if (tim_p->tm_year > 70)
+ {
+ for (year = 70; year < tim_p->tm_year; year++)
+ days += _DAYS_IN_YEAR (year);
+ }
+ else if (tim_p->tm_year < 70)
+ {
+ for (year = 69; year > tim_p->tm_year; year--)
+ days -= _DAYS_IN_YEAR (year);
+ days -= _DAYS_IN_YEAR (year);
+ }
+
+ /* compute day of the week */
+ if ((tim_p->tm_wday = (days + 4) % 7) < 0)
+ tim_p->tm_wday += 7;
+
+ /* compute total seconds */
+ tim += (days * _SEC_IN_DAY);
+
+ return tim;
+}
diff --git a/libc/time/strftime.c b/libc/time/strftime.c
new file mode 100644
index 0000000..1e6154f
--- /dev/null
+++ b/libc/time/strftime.c
@@ -0,0 +1,444 @@
+/*
+ * strftime.c
+ * Original Author: G. Haley
+ *
+ * Places characters into the array pointed to by s as controlled by the string
+ * pointed to by format. If the total number of resulting characters including
+ * the terminating null character is not more than maxsize, returns the number
+ * of characters placed into the array pointed to by s (not including the
+ * terminating null character); otherwise zero is returned and the contents of
+ * the array indeterminate.
+ */
+
+/*
+FUNCTION
+<<strftime>>---flexible calendar time formatter
+
+INDEX
+ strftime
+
+ANSI_SYNOPSIS
+ #include <time.h>
+ size_t strftime(char *<[s]>, size_t <[maxsize]>,
+ const char *<[format]>, const struct tm *<[timp]>);
+
+TRAD_SYNOPSIS
+ #include <time.h>
+ size_t strftime(<[s]>, <[maxsize]>, <[format]>, <[timp]>)
+ char *<[s]>;
+ size_t <[maxsize]>;
+ char *<[format]>;
+ struct tm *<[timp]>;
+
+DESCRIPTION
+<<strftime>> converts a <<struct tm>> representation of the time (at
+<[timp]>) into a string, starting at <[s]> and occupying no more than
+<[maxsize]> characters.
+
+You control the format of the output using the string at <[format]>.
+<<*<[format]>>> can contain two kinds of specifications: text to be
+copied literally into the formatted string, and time conversion
+specifications. Time conversion specifications are two-character
+sequences beginning with `<<%>>' (use `<<%%>>' to include a percent
+sign in the output). Each defined conversion specification selects a
+field of calendar time data from <<*<[timp]>>>, and converts it to a
+string in one of the following ways:
+
+o+
+o %a
+An abbreviation for the day of the week.
+
+o %A
+The full name for the day of the week.
+
+o %b
+An abbreviation for the month name.
+
+o %B
+The full name of the month.
+
+o %c
+A string representing the complete date and time, in the form
+. Mon Apr 01 13:13:13 1992
+
+o %d
+The day of the month, formatted with two digits.
+
+o %H
+The hour (on a 24-hour clock), formatted with two digits.
+
+o %I
+The hour (on a 12-hour clock), formatted with two digits.
+
+o %j
+The count of days in the year, formatted with three digits
+(from `<<001>>' to `<<366>>').
+
+o %m
+The month number, formatted with two digits.
+
+o %M
+The minute, formatted with two digits.
+
+o %p
+Either `<<AM>>' or `<<PM>>' as appropriate.
+
+o %S
+The second, formatted with two digits.
+
+o %U
+The week number, formatted with two digits (from `<<00>>' to `<<53>>';
+week number 1 is taken as beginning with the first Sunday in a year).
+See also <<%W>>.
+
+o %w
+A single digit representing the day of the week: Sunday is day <<0>>.
+
+o %W
+Another version of the week number: like `<<%U>>', but counting week 1
+as beginning with the first Monday in a year.
+
+o
+o %x
+A string representing the complete date, in a format like
+. Mon Apr 01 1992
+
+o %X
+A string representing the full time of day (hours, minutes, and
+seconds), in a format like
+. 13:13:13
+
+o %y
+The last two digits of the year.
+
+o %Y
+The full year, formatted with four digits to include the century.
+
+o %Z
+Defined by ANSI C as eliciting the time zone if available; it is not
+available in this implementation (which accepts `<<%Z>>' but generates
+no output for it).
+
+o %%
+A single character, `<<%>>'.
+o-
+
+RETURNS
+When the formatted time takes up no more than <[maxsize]> characters,
+the result is the length of the formatted string. Otherwise, if the
+formatting operation was abandoned due to lack of room, the result is
+<<0>>, and the string starting at <[s]> corresponds to just those
+parts of <<*<[format]>>> that could be completely filled in within the
+<[maxsize]> limit.
+
+PORTABILITY
+ANSI C requires <<strftime>>, but does not specify the contents of
+<<*<[s]>>> when the formatted string would require more than
+<[maxsize]> characters.
+
+<<strftime>> requires no supporting OS subroutines.
+*/
+
+#include <stddef.h>
+#include <stdio.h>
+#include <time.h>
+
+static _CONST int dname_len[7] =
+{6, 6, 7, 9, 8, 6, 8};
+
+static _CONST char *_CONST dname[7] =
+{"Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday"};
+
+static _CONST int mname_len[12] =
+{7, 8, 5, 5, 3, 4, 4, 6, 9, 7, 8, 8};
+
+static _CONST char *_CONST mname[12] =
+{"January", "February", "March", "April",
+ "May", "June", "July", "August", "September", "October", "November",
+ "December"};
+
+size_t
+_DEFUN (strftime, (s, maxsize, format, tim_p),
+ char *s _AND
+ size_t maxsize _AND
+ _CONST char *format _AND
+ _CONST struct tm *tim_p)
+{
+ size_t count = 0;
+ int i;
+
+ for (;;)
+ {
+ while (*format && *format != '%')
+ {
+ if (count < maxsize - 1)
+ s[count++] = *format++;
+ else
+ return 0;
+ }
+
+ if (*format == '\0')
+ break;
+
+ format++;
+ switch (*format)
+ {
+ case 'a':
+ for (i = 0; i < 3; i++)
+ {
+ if (count < maxsize - 1)
+ s[count++] =
+ dname[tim_p->tm_wday][i];
+ else
+ return 0;
+ }
+ break;
+ case 'A':
+ for (i = 0; i < dname_len[tim_p->tm_wday]; i++)
+ {
+ if (count < maxsize - 1)
+ s[count++] =
+ dname[tim_p->tm_wday][i];
+ else
+ return 0;
+ }
+ break;
+ case 'b':
+ for (i = 0; i < 3; i++)
+ {
+ if (count < maxsize - 1)
+ s[count++] =
+ mname[tim_p->tm_mon][i];
+ else
+ return 0;
+ }
+ break;
+ case 'B':
+ for (i = 0; i < mname_len[tim_p->tm_mon]; i++)
+ {
+ if (count < maxsize - 1)
+ s[count++] =
+ mname[tim_p->tm_mon][i];
+ else
+ return 0;
+ }
+ break;
+ case 'c':
+ if (count < maxsize - 24)
+ {
+ for (i = 0; i < 3; i++)
+ s[count++] =
+ dname[tim_p->tm_wday][i];
+ s[count++] = ' ';
+ for (i = 0; i < 3; i++)
+ s[count++] =
+ mname[tim_p->tm_mon][i];
+
+ sprintf (&s[count],
+ " %.2d %2.2d:%2.2d:%2.2d %.4d",
+ tim_p->tm_mday, tim_p->tm_hour,
+ tim_p->tm_min,
+ tim_p->tm_sec, 1900 +
+ tim_p->tm_year);
+ count += 17;
+ }
+ else
+ return 0;
+ break;
+ case 'd':
+ if (count < maxsize - 2)
+ {
+ sprintf (&s[count], "%.2d",
+ tim_p->tm_mday);
+ count += 2;
+ }
+ else
+ return 0;
+ break;
+ case 'H':
+ if (count < maxsize - 2)
+ {
+ sprintf (&s[count], "%2.2d",
+ tim_p->tm_hour);
+ count += 2;
+ }
+ else
+ return 0;
+ break;
+ case 'I':
+ if (count < maxsize - 2)
+ {
+ if (tim_p->tm_hour == 0 ||
+ tim_p->tm_hour == 12)
+ {
+ s[count++] = '1';
+ s[count++] = '2';
+ }
+ else
+ {
+ sprintf (&s[count], "%.2d",
+ tim_p->tm_hour % 12);
+ count += 2;
+ }
+ }
+ else
+ return 0;
+ break;
+ case 'j':
+ if (count < maxsize - 3)
+ {
+ sprintf (&s[count], "%.3d",
+ tim_p->tm_yday + 1);
+ count += 3;
+ }
+ else
+ return 0;
+ break;
+ case 'm':
+ if (count < maxsize - 2)
+ {
+ sprintf (&s[count], "%.2d",
+ tim_p->tm_mon + 1);
+ count += 2;
+ }
+ else
+ return 0;
+ break;
+ case 'M':
+ if (count < maxsize - 2)
+ {
+ sprintf (&s[count], "%2.2d",
+ tim_p->tm_min);
+ count += 2;
+ }
+ else
+ return 0;
+ break;
+ case 'p':
+ if (count < maxsize - 2)
+ {
+ if (tim_p->tm_hour < 12)
+ s[count++] = 'A';
+ else
+ s[count++] = 'P';
+
+ s[count++] = 'M';
+ }
+ else
+ return 0;
+ break;
+ case 'S':
+ if (count < maxsize - 2)
+ {
+ sprintf (&s[count], "%2.2d",
+ tim_p->tm_sec);
+ count += 2;
+ }
+ else
+ return 0;
+ break;
+ case 'U':
+ if (count < maxsize - 2)
+ {
+ sprintf (&s[count], "%2.2d",
+ (tim_p->tm_yday + 7 -
+ tim_p->tm_wday) / 7);
+ count += 2;
+ }
+ else
+ return 0;
+ break;
+ case 'w':
+ if (count < maxsize - 1)
+ {
+ sprintf (&s[count], "%1.1d",
+ tim_p->tm_wday);
+ count++;
+ }
+ else
+ return 0;
+ break;
+ case 'W':
+ if (count < maxsize - 2)
+ {
+ sprintf (&s[count], "%2.2d",
+ (tim_p->tm_yday + ((8 -
+ tim_p->tm_wday) % 7)) / 7);
+ count += 2;
+ }
+ else
+ return 0;
+ break;
+ case 'x':
+ if (count < maxsize - 15)
+ {
+ for (i = 0; i < 3; i++)
+ s[count++] =
+ dname[tim_p->tm_wday][i];
+ s[count++] = ' ';
+ for (i = 0; i < 3; i++)
+ s[count++] =
+ mname[tim_p->tm_mon][i];
+
+ sprintf (&s[count],
+ " %.2d %.4d", tim_p->tm_mday,
+ 1900 + tim_p->tm_year);
+ count += 8;
+ }
+ else
+ return 0;
+ break;
+ case 'X':
+ if (count < maxsize - 8)
+ {
+ sprintf (&s[count],
+ "%2.2d:%2.2d:%2.2d",
+ tim_p->tm_hour, tim_p->tm_min,
+ tim_p->tm_sec);
+ count += 8;
+ }
+ else
+ return 0;
+ break;
+ case 'y':
+ if (count < maxsize - 2)
+ {
+ /* The year could be greater than 100, so we need the value
+ modulo 100. The year could be negative, so we need to
+ correct for a possible negative remainder. */
+ sprintf (&s[count], "%2.2d",
+ (tim_p->tm_year % 100 + 100) % 100);
+ count += 2;
+ }
+ else
+ return 0;
+ break;
+ case 'Y':
+ if (count < maxsize - 4)
+ {
+ sprintf (&s[count], "%.4d",
+ 1900 + tim_p->tm_year);
+ count += 4;
+ }
+ else
+ return 0;
+ break;
+ case 'Z':
+ break;
+ case '%':
+ if (count < maxsize - 1)
+ s[count++] = '%';
+ else
+ return 0;
+ break;
+ }
+ if (*format)
+ format++;
+ else
+ break;
+ }
+ s[count] = '\0';
+
+ return count;
+}
diff --git a/libc/time/time.c b/libc/time/time.c
new file mode 100644
index 0000000..38cce50
--- /dev/null
+++ b/libc/time/time.c
@@ -0,0 +1,59 @@
+/* FIXME: doc says "not avail" due to #if 0.
+ DELETE that line if inappropriate! */
+/*
+FUNCTION
+<<time>>---get current calendar time (as single number)
+
+INDEX
+ time
+
+ANSI_SYNOPSIS
+ #include <time.h>
+ time_t time(time_t *<[t]>);
+
+TRAD_SYNOPSIS
+ #include <time.h>
+ time_t time(<[t]>)
+ time_t *<[t]>;
+
+DESCRIPTION
+<<time>> looks up the best available representation of the current
+time and returns it, encoded as a <<time_t>>. It stores the same
+value at <[t]> unless the argument is <<NULL>>.
+
+RETURNS
+A <<-1>> result means the current time is not available; otherwise the
+result represents the current time.
+
+PORTABILITY
+ANSI C requires <<time>>.
+
+Supporting OS subroutine required: Some implementations require
+<<gettimeofday>>.
+*/
+
+#ifdef HAVE_GETTIMEOFDAY
+
+/* Most times we have a system call in newlib/libc/sys/.. to do this job */
+
+#include <_ansi.h>
+#include <reent.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+time_t
+_DEFUN (time, (t),
+ time_t * t)
+{
+ struct timeval now;
+
+ if (_gettimeofday_r (_REENT, &now, (struct timezone *) 0) >= 0)
+ {
+ if (t)
+ *t = now.tv_sec;
+ return now.tv_sec;
+ }
+ return -1;
+}
+
+#endif