
(cond-expand
 (plan9)
 (windows
  (c-system-include "sys/types.h"))
 (else
  (c-system-include "time.h")
  (c-system-include "sys/time.h")))

(cond-expand
 (solaris
    (define-c-struct tm
    predicate: tm?
    constructor: (make-tm tm_sec tm_min tm_hour
                          tm_mday tm_mon tm_year tm_isdst)
    (int     tm_sec    time-second)
    (int     tm_min    time-minute)
    (int     tm_hour   time-hour)
    (int     tm_mday   time-day)
    (int     tm_mon    time-month)
    (int     tm_year   time-year)
    (int     tm_wday   time-day-of-week)
    (int     tm_yday   time-day-of-year)
    (int     tm_isdst  time-dst?)))
 (else
  (define-c-struct tm
    predicate: tm?
    constructor: (make-tm tm_sec tm_min tm_hour
                          tm_mday tm_mon tm_year tm_isdst)
    (int     tm_sec    time-second)
    (int     tm_min    time-minute)
    (int     tm_hour   time-hour)
    (int     tm_mday   time-day)
    (int     tm_mon    time-month)
    (int     tm_year   time-year)
    (int     tm_wday   time-day-of-week)
    (int     tm_yday   time-day-of-year)
    (int     tm_isdst  time-dst?)
    (string  tm_zone   time-timezone-name)
    (int     tm_gmtoff time-offset))))

;;> Accessors for the \scheme{tm} struct.
;;/

(define-c-struct timeval
  predicate: timeval?
  constructor: (make-timeval tv_sec tv_usec)
  (time_t  tv_sec          timeval-seconds)
  (int     tv_usec         timeval-microseconds))

;;> Accessors for the \scheme{timeval} struct.
;;/

(define-c-struct timezone
  predicate: timezone?
  (int     tz_minuteswest  timezone-offset)
  (int     tz_dsttime      timezone-dst-time))

;;> Accessors for the \scheme{timezone} struct.
;;/

;;> Returns the current time as an integer number
;;> of seconds since an arbitrary epoch.

(define-c time_t (current-seconds "time") ((value NULL)))

;;> Returns the current time as a list of a timeval struct
;;> and a timezone.

(define-c errno (get-time-of-day "gettimeofday")
  ((result timeval) (result timezone)))

;;> Set the current time from a timeval struct and
;;> and optional timezone.

(cond-expand
  (emscripten)
  (else
    (define-c errno (set-time-of-day! "settimeofday")
      (timeval (maybe-null default NULL timezone)))))

;;> Convert an integer number of epoch seconds to a broken-down tm struct.

(define-c non-null-pointer (seconds->time "localtime_r")
  ((pointer time_t) (result tm)))

;;> Convert a tm struct to an integer number of seconds.

(define-c time_t (time->seconds "mktime")
  (tm))

;;> Format a datetime string from an integer number of epoch seconds.

(define-c non-null-string (seconds->string "ctime_r")
  ((pointer time_t) (result (array char 64))))

;;> Format a datetime string from a tm struct.

(define-c non-null-string (time->string "asctime_r")
  (tm (result (array char 64))))

(cond-expand
 ((or bsd linux)
  (c-system-include "sys/resource.h")
  (define-c-struct rusage
    predicate: rusage?
    ((struct timeval) ru_utime  resource-usage-time)
    ((struct timeval) ru_stime  resource-usage-system-time)
    (long             ru_maxrss resource-usage-max-rss))

;;> Accessors for the \scheme{rusage} struct.
;;/

  (define-c-const int (resource-usage/self RUSAGE_SELF))
  (define-c-const int (resource-usage/children RUSAGE_CHILDREN))

;;> Returns a struct describing the resources used by the current
;;> process.

  (define-c errno (get-resource-usage "getrusage")
    ((default RUSAGE_SELF int) (result rusage))))
 (else
  ))
