Initial import

This commit is contained in:
Justine Tunney 2020-06-15 07:18:57 -07:00
commit c91b3c5006
14915 changed files with 590219 additions and 0 deletions

48
libc/time/alarm.c Normal file
View file

@ -0,0 +1,48 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/calls/struct/itimerval.h"
#include "libc/macros.h"
#include "libc/math.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/itimer.h"
#include "libc/time/time.h"
/**
* Asks for single-shot SIGALRM to be raise()'d after interval.
*
* @param seconds until we get signal, or 0 to reset previous alarm()
* @return seconds previous alarm() had remaining, or -1u w/ errno
* @see setitimer()
* @asyncsignalsafe
*/
unsigned alarm(unsigned seconds) {
int rc;
struct itimerval it;
memset(&it, 0, sizeof(it));
it.it_value.tv_sec = seconds;
rc = setitimer(ITIMER_REAL, &it, &it);
assert(rc != -1);
if (!it.it_value.tv_sec && !it.it_value.tv_usec) {
return 0;
} else {
return MIN(1, it.it_value.tv_sec + (it.it_value.tv_usec > 5000000));
}
}

24
libc/time/asctime.c Normal file
View file

@ -0,0 +1,24 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/time/time.h"
static char g_asctime_buf[64];
char *asctime(const struct tm *date) { return asctime_r(date, g_asctime_buf); }

37
libc/time/asctime_r.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/fmt/fmt.h"
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
STATIC_YOINK("ntoa");
STATIC_YOINK("stoa");
static unsigned clip(unsigned index, unsigned count) {
return index < count ? index : 0;
}
char *asctime_r(const struct tm *date, char *buf /*[64]*/) {
(snprintf)(buf, 64, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
kWeekdayNameShort[clip(date->tm_wday, 7)],
kMonthNameShort[clip(date->tm_mon, 12)], date->tm_mday,
date->tm_hour, date->tm_min, date->tm_sec, 1900 + date->tm_year);
return buf;
}

34
libc/time/clock.c Normal file
View file

@ -0,0 +1,34 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/struct/timespec.h"
#include "libc/sysv/consts/clock.h"
#include "libc/time/time.h"
/**
* Returns how much CPU program has consumed on time-sharing system.
*
* @return value that can be divided by CLOCKS_PER_SEC, or -1 w/ errno
*/
int64_t clock(void) {
struct timespec ts;
if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) == -1) return -1;
return ts.tv_sec * CLOCKS_PER_SEC +
ts.tv_nsec / (1000000000 / CLOCKS_PER_SEC);
}

76
libc/time/clock_gettime.c Normal file
View file

@ -0,0 +1,76 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
#include "libc/conv/conv.h"
#include "libc/dce.h"
#include "libc/mach.h"
#include "libc/nt/struct/filetime.h"
#include "libc/nt/struct/systemtime.h"
#include "libc/nt/synchronization.h"
#include "libc/sysv/consts/clock.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
/**
* Returns nanosecond time.
*
* This is a high-precision timer that supports multiple definitions of
* time. Among the more popular is CLOCK_MONOTONIC. This function has a
* zero syscall implementation of that on modern x86.
*
* @param clockid can be CLOCK_REALTIME, CLOCK_MONOTONIC, etc. noting
* that on Linux CLOCK_MONOTONIC is redefined to use the monotonic
* clock that's actually monotonic lool
* @param out_ts is where the nanoseconds are stored
* @return 0 on success or -1 w/ errno on error
* @error ENOSYS if clockid isn't available; in which case this function
* guarantees an ordinary timestamp is still stored to out_ts; and
* errno isn't restored to its original value, to detect prec. loss
* @see strftime(), gettimeofday()
* @asyncsignalsafe
*/
int clock_gettime(int clockid, struct timespec *out_ts) {
/* TODO(jart): Just ignore O/S for MONOTONIC and measure RDTSC on start */
if (!IsWindows()) {
if (!IsXnu()) {
out_ts->tv_sec = 0;
out_ts->tv_nsec = 0;
return clock_gettime$sysv(clockid, out_ts);
} else {
static_assert(sizeof(struct timeval) == sizeof(struct timespec));
out_ts->tv_sec = 0;
out_ts->tv_nsec = 0;
int rc = gettimeofday$sysv((struct timeval *)out_ts, NULL);
out_ts->tv_nsec *= 1000;
return rc;
}
} else {
struct NtFileTime ft;
GetSystemTimeAsFileTime(&ft);
filetimetotimespec(out_ts, ft);
return 0;
}
}

22
libc/time/ctime.c Normal file
View file

@ -0,0 +1,22 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/time/time.h"
char *ctime(const int64_t *timep) { return asctime(localtime(timep)); }

26
libc/time/ctime_r.c Normal file
View file

@ -0,0 +1,26 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
char *ctime_r(const int64_t *timep, char *buf /*[64]*/) {
struct tm date[1];
return asctime_r(localtime_r(timep, date), buf);
}

22
libc/time/difftime.c Normal file
View file

@ -0,0 +1,22 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/time/time.h"
double difftime(int64_t x, int64_t y) { return x - y; }

42
libc/time/dsleep.c Normal file
View file

@ -0,0 +1,42 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/struct/timespec.h"
#include "libc/math.h"
#include "libc/nexgen32e/nexgen32e.h"
#include "libc/time/time.h"
/**
* Sleeps w/ higher precision.
*/
long double dsleep(long double secs) {
struct timespec dur, rem;
dur.tv_sec = secs;
dur.tv_nsec = secs * 1e9;
dur.tv_nsec = mod1000000000int64(dur.tv_nsec);
if (secs > 1e-6) {
nanosleep(&dur, &rem);
secs = rem.tv_nsec;
secs *= 1 / 1e9;
secs += rem.tv_sec;
return secs;
} else {
return 0;
}
}

37
libc/time/dtime.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/assert.h"
#include "libc/calls/struct/timespec.h"
#include "libc/str/str.h"
#include "libc/time/time.h"
/**
* Returns seconds since epoch w/ high-precision.
* @param clockid can be CLOCK_{REALTIME,MONOTONIC}, etc.
*/
long double dtime(int clockid) {
long double secs;
struct timespec tv;
clock_gettime(clockid, &tv);
secs = tv.tv_nsec;
secs *= 1 / 1e9;
secs += tv.tv_sec;
return secs;
}

37
libc/time/getitimer.c Normal file
View file

@ -0,0 +1,37 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dce.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
/**
* Retrieves last setitimer() value, correcting for remaining time.
*
* @param which can be ITIMER_REAL, ITIMER_VIRTUAL, etc.
* @return 0 on success or -1 w/ errno
*/
int getitimer(int which, struct itimerval *curvalue) {
if (!IsWindows()) {
int getitimer$sysv(int, struct itimerval *) hidden;
return getitimer$sysv(which, curvalue);
} else {
return enosys(); /* TODO(jart): Implement me! */
}
}

View file

@ -0,0 +1,35 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/timeval.h"
#include "libc/conv/conv.h"
#include "libc/nt/struct/filetime.h"
#include "libc/nt/struct/systemtime.h"
#include "libc/nt/synchronization.h"
#include "libc/str/str.h"
#include "libc/time/struct/timezone.h"
int gettimeofday$nt(struct timeval *tv, struct timezone *tz) {
struct NtFileTime ft;
GetSystemTimeAsFileTime(&ft);
filetimetotimeval(tv, ft);
if (tz) memset(tz, 0, sizeof(*tz));
return 0;
}

View file

@ -0,0 +1,54 @@
/*-*- mode:asm; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dce.h"
#include "libc/macros.h"
/ Returns system wall time in microseconds.
/
/ @param rdi points to timeval that receives result
/ @param rsi receives UTC timezone if non-NULL
/ @return always zero
/ @see clock_gettime() for nanosecond precision
/ @see strftime() for string formatting
gettimeofday$sysv:
push %rbp
mov %rsp,%rbp
.profilable
test %rsi,%rsi
jz 1f
push $0
pop (%rsi)
1: xor %esi,%esi # no one zones this way.
xor %edx,%edx # i64*mach_absolute_time
call __gettimeofday$sysv
#if SupportsXnu()
testb IsXnu() # XNU might do %rax:%rdx
jz 1f
test %rdi,%rdi
jz 1f
test %rax,%rax
jz 1f
mov %rax,(%rdi)
mov %rdx,8(%rdi)
#endif
1: xor %eax,%eax # nevar fail
pop %rbp
ret
.endfn gettimeofday$sysv,globl,hidden

39
libc/time/gettimeofday.c Normal file
View file

@ -0,0 +1,39 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/time/time.h"
/**
* Returns system wall time in microseconds.
*
* @param tv points to timeval that receives result
* @param tz receives UTC timezone if non-NULL
* @return always zero
* @see clock_gettime() for nanosecond precision
* @see strftime() for string formatting
*/
int gettimeofday(struct timeval *tv, struct timezone *tz) {
if (!IsWindows()) {
return gettimeofday$sysv(tv, tz);
} else {
return gettimeofday$nt(tv, tz);
}
}

28
libc/time/kmonthname.S Normal file
View file

@ -0,0 +1,28 @@
#if 0
/*
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/
http://creativecommons.org/publicdomain/zero/1.0/
*/
#endif
#include "libc/macros.inc"
/ extern const char kMonthName[12][10];
.section .rodata,"aS",@progbits
kMonthName:
.ascin "January",10
.ascin "February",10
.ascin "March",10
.ascin "April",10
.ascin "May",10
.ascin "June",10
.ascin "July",10
.ascin "August",10
.ascin "September",10
.ascin "October",10
.ascin "November",10
.ascin "December",10
.endobj kMonthName,globl
.previous

View file

@ -0,0 +1,34 @@
#if 0
/*
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/
http://creativecommons.org/publicdomain/zero/1.0/
*/
#endif
#include "libc/macros.inc"
/ Type #1:
/ - Indexable C-String Array
/ - extern const char kMonthNameShort[12][4];
/ Type #2:
/ - Double-NUL Terminated String
/ - extern const char kMonthNameShort[];
.section .rodata,"aS",@progbits
kMonthNameShort:
.ascin "Jan",4
.ascin "Feb",4
.ascin "Mar",4
.ascin "Apr",4
.ascin "May",4
.ascin "Jun",4
.ascin "Jul",4
.ascin "Aug",4
.ascin "Sep",4
.ascin "Oct",4
.ascin "Nov",4
.ascin "Dec",4
.byte 0
.endobj kMonthNameShort,globl
.previous

23
libc/time/kweekdayname.S Normal file
View file

@ -0,0 +1,23 @@
#if 0
/*
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/
http://creativecommons.org/publicdomain/zero/1.0/
*/
#endif
#include "libc/macros.inc"
/ extern const char kWeekdayName[7][10];
.section .rodata,"aS",@progbits
kWeekdayName:
.ascin "Sunday",10
.ascin "Monday",10
.ascin "Tuesday",10
.ascin "Wednesday",10
.ascin "Thursday",10
.ascin "Friday",10
.ascin "Saturday",10
.endobj kWeekdayName,globl
.previous

View file

@ -0,0 +1,29 @@
#if 0
/*
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/
http://creativecommons.org/publicdomain/zero/1.0/
*/
#endif
#include "libc/macros.inc"
/ Type #1:
/ - Indexable C-String Array
/ - extern const char kWeekdayNameShort[7][4];
/ Type #2:
/ - Double-NUL Terminated String
/ - extern const char kWeekdayNameShort[];
.section .rodata,"aS",@progbits
kWeekdayNameShort:
.asciz "Sun"
.asciz "Mon"
.asciz "Tue"
.asciz "Wed"
.asciz "Thu"
.asciz "Fri"
.asciz "Sat"
.byte 0
.endobj kWeekdayNameShort,globl
.previous

2045
libc/time/localtime.c Normal file

File diff suppressed because it is too large Load diff

58
libc/time/nanosleep.c Normal file
View file

@ -0,0 +1,58 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
#include "libc/conv/conv.h"
#include "libc/dce.h"
#include "libc/macros.h"
#include "libc/nt/enum/status.h"
#include "libc/nt/errors.h"
#include "libc/nt/nt/time.h"
#include "libc/nt/synchronization.h"
#include "libc/sock/internal.h"
#include "libc/sysv/errfuns.h"
/**
* Sleeps for a particular amount of time.
*/
int nanosleep(const struct timespec *req, struct timespec *rem) {
long res, millis, hectonanos;
if (!IsWindows()) {
if (!IsXnu()) {
return nanosleep$sysv(req, rem);
} else {
return select$sysv(0, 0, 0, 0, /* lool */
&(struct timeval){req->tv_sec, req->tv_nsec / 1000});
}
} else {
if (req->tv_sec && req->tv_nsec) {
hectonanos = MAX(1, req->tv_sec * 10000000L + req->tv_nsec / 100L);
} else {
hectonanos = 1;
}
if (NtError(NtDelayExecution(true, &hectonanos))) {
millis = hectonanos / 10000;
res = SleepEx(millis, true);
if (res == kNtWaitIoCompletion) return eintr();
}
return 0;
}
}

89
libc/time/now.c Normal file
View file

@ -0,0 +1,89 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nexgen32e/x86feature.h"
#include "libc/sysv/consts/clock.h"
#include "libc/time/time.h"
static struct Now {
uint64_t k0;
long double r0, cpn;
} now_;
/**
* Returns timestamp without needing system calls.
* @note uses microsecond scale fallback on k8 or vm
*/
long double (*nowl)(void);
long double converttickstonanos(uint64_t ticks) {
return ticks * now_.cpn; /* pico scale */
}
long double converttickstoseconds(uint64_t ticks) {
return 1 / 1e9 * converttickstonanos(ticks);
}
static long double nowl$sys(void) {
return dtime(CLOCK_REALTIME);
}
static long double nowl$art(void) {
uint64_t ticks;
ticks = unsignedsubtract(rdtsc(), now_.k0);
return now_.r0 + converttickstoseconds(ticks);
}
static long double GetSample(void) {
uint64_t tick1, tick2;
long double time1, time2;
sched_yield();
time1 = dtime(CLOCK_MONOTONIC);
tick1 = rdtsc();
nanosleep(&(struct timespec){0, 100000}, NULL);
time2 = dtime(CLOCK_MONOTONIC);
tick2 = rdtsc();
return (time2 - time1) * 1e9 / (tick2 - tick1);
}
static long double MeasureNanosPerCycle(void) {
int i;
long double avg, samp;
for (avg = 1.0L, i = 1; i < 5; ++i) {
samp = GetSample();
avg += (samp - avg) / i;
}
return avg;
}
INITIALIZER(301, _init_time, {
if (X86_HAVE(INVTSC)) {
now_.cpn = MeasureNanosPerCycle();
now_.r0 = dtime(CLOCK_REALTIME);
now_.k0 = rdtsc();
nowl = nowl$art;
} else {
nowl = nowl$sys;
}
})

54
libc/time/setitimer.c Normal file
View file

@ -0,0 +1,54 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/itimerval.h"
#include "libc/dce.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
/**
* Schedules delivery of one-shot or intermittent wakeup signal, e.g.
*
* CHECK_NE(-1, sigaction(SIGALRM,
* &(struct sigaction){.sa_sigaction = missingno,
* .sa_flags = SA_RESETHAND},
* NULL));
* CHECK_NE(-1, setitimer(ITIMER_REAL,
* &(const struct itimerval){{0, 0}, {0, 50000}},
* NULL));
* if (connect(...) == -1 && errno == EINTR) { ... }
* CHECK_NE(-1, setitimer(ITIMER_REAL,
* &(const struct itimerval){{0, 0}, {0, 0}},
* NULL));
*
* @param which can be ITIMER_REAL, ITIMER_VIRTUAL, etc.
* @param newvalue specifies the interval ({0,0} means one-shot) and
* duration ({0,0} means disarm) in microseconds
* @param out_opt_old may receive remainder of previous op (if any)
* @return 0 on success or -1 w/ errno
*/
int setitimer(int which, const struct itimerval *newvalue,
struct itimerval *out_opt_oldvalue) {
if (!IsWindows()) {
return setitimer$sysv(which, newvalue, out_opt_oldvalue);
} else {
return enosys(); /* TODO(jart): Implement me! */
}
}

29
libc/time/sleep.c Normal file
View file

@ -0,0 +1,29 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/struct/timespec.h"
#include "libc/time/time.h"
/**
* Sleeps for a particular amount of time.
* @asyncsignalsafe
*/
int sleep(uint32_t seconds) {
return nanosleep(&(struct timespec){seconds, 0}, NULL);
}

380
libc/time/strftime.c Normal file
View file

@ -0,0 +1,380 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright (c) 1989 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms are permitted
provided that the above copyright notice and this paragraph are
duplicated in all such forms and that any documentation,
advertising materials, and other materials related to such
distribution and use acknowledge that the software was developed
by the University of California, Berkeley. The name of the
University may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "libc/calls/calls.h"
#include "libc/fmt/fmt.h"
#include "libc/macros.h"
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
#include "libc/tzfile.h"
STATIC_YOINK("ntoa");
asm(".ident\t\"\\n\\n\
strftime (BSD-3)\\n\
Copyright 1989 The Regents of the University of California\"");
asm(".include \"libc/disclaimer.inc\"");
static char *strftime_add(char *pt, const char *ptlim, const char *str) {
while (pt < ptlim && (*pt = *str++) != '\0') ++pt;
return pt;
}
static char *strftime_conv(char *pt, const char *ptlim, int n,
const char *format) {
char buf[INT_STRLEN_MAXIMUM(int) + 1];
(snprintf)(buf, sizeof(buf), format, n);
return strftime_add(pt, ptlim, buf);
}
static char *strftime_secs(char *pt, const char *ptlim, const struct tm *t) {
static char buf[INT_STRLEN_MAXIMUM(int) + 1];
struct tm tmp;
int64_t s;
tmp = *t; /* Make a copy, mktime(3) modifies the tm struct. */
s = mktime(&tmp);
(snprintf)(buf, sizeof(buf), "%ld", s);
return strftime_add(pt, ptlim, buf);
}
static char *strftime_timefmt(char *pt, const char *ptlim, const char *format,
const struct tm *t) {
int i;
long diff;
char const *sign;
/* size_t z1, z2, z3; */
for (; *format; ++format) {
if (*format == '%') {
label:
switch (*++format) {
case '\0':
--format;
break;
case 'A':
pt = strftime_add(pt, ptlim,
(t->tm_wday < 0 || t->tm_wday > 6)
? "?"
: kWeekdayName[t->tm_wday]);
continue;
case 'a':
pt = strftime_add(pt, ptlim,
(t->tm_wday < 0 || t->tm_wday > 6)
? "?"
: kWeekdayNameShort[t->tm_wday]);
continue;
case 'B':
pt = strftime_add(
pt, ptlim,
(t->tm_mon < 0 || t->tm_mon > 11) ? "?" : kMonthName[t->tm_mon]);
continue;
case 'b':
case 'h':
pt = strftime_add(pt, ptlim,
(t->tm_mon < 0 || t->tm_mon > 11)
? "?"
: kMonthNameShort[t->tm_mon]);
continue;
case 'c':
pt = strftime_timefmt(pt, ptlim, "%D %X", t);
continue;
case 'C':
/*
** %C used to do a...
** strftime_timefmt("%a %b %e %X %Y", t);
** ...whereas now POSIX 1003.2 calls for
** something completely different.
** (ado, 5/24/93)
*/
pt = strftime_conv(pt, ptlim, (t->tm_year + TM_YEAR_BASE) / 100,
"%02d");
continue;
case 'D':
pt = strftime_timefmt(pt, ptlim, "%m/%d/%y", t);
continue;
case 'x':
/*
** Version 3.0 of strftime from Arnold Robbins
** (arnold@skeeve.atl.ga.us) does the
** equivalent of...
** strftime_timefmt("%a %b %e %Y");
** ...for %x; since the X3J11 C language
** standard calls for "date, using locale's
** date format," anything goes. Using just
** numbers (as here) makes Quakers happier.
** Word from Paul Eggert (eggert@twinsun.com)
** is that %Y-%m-%d is the ISO standard date
** format, specified in ISO 2014 and later
** ISO 8601:1988, with a summary available in
** pub/doc/ISO/english/ISO8601.ps.Z on
** ftp.uni-erlangen.de.
** (ado, 5/30/93)
*/
pt = strftime_timefmt(pt, ptlim, "%m/%d/%y", t);
continue;
case 'd':
pt = strftime_conv(pt, ptlim, t->tm_mday, "%02d");
continue;
case 'E':
case 'O':
/*
** POSIX locale extensions, a la
** Arnold Robbins' strftime version 3.0.
** The sequences
** %Ec %EC %Ex %Ey %EY
** %Od %oe %OH %OI %Om %OM
** %OS %Ou %OU %OV %Ow %OW %Oy
** are supposed to provide alternate
** representations.
** (ado, 5/24/93)
*/
goto label;
case 'e':
pt = strftime_conv(pt, ptlim, t->tm_mday, "%2d");
continue;
case 'H':
pt = strftime_conv(pt, ptlim, t->tm_hour, "%02d");
continue;
case 'I':
pt = strftime_conv(
pt, ptlim, (t->tm_hour % 12) ? (t->tm_hour % 12) : 12, "%02d");
continue;
case 'j':
pt = strftime_conv(pt, ptlim, t->tm_yday + 1, "%03d");
continue;
case 'k':
/*
** This used to be...
** strftime_conv(t->tm_hour % 12 ?
** t->tm_hour % 12 : 12, 2, ' ');
** ...and has been changed to the below to
** match SunOS 4.1.1 and Arnold Robbins'
** strftime version 3.0. That is, "%k" and
** "%l" have been swapped.
** (ado, 5/24/93)
*/
pt = strftime_conv(pt, ptlim, t->tm_hour, "%2d");
continue;
#ifdef KITCHEN_SINK
case 'K':
/*
** After all this time, still unclaimed!
*/
pt = strftime_add(pt, ptlim, "kitchen sink");
continue;
#endif /* defined KITCHEN_SINK */
case 'l':
/*
** This used to be...
** strftime_conv(t->tm_hour, 2, ' ');
** ...and has been changed to the below to
** match SunOS 4.1.1 and Arnold Robbin's
** strftime version 3.0. That is, "%k" and
** "%l" have been swapped.
** (ado, 5/24/93)
*/
pt = strftime_conv(pt, ptlim,
(t->tm_hour % 12) ? (t->tm_hour % 12) : 12, "%2d");
continue;
case 'M':
pt = strftime_conv(pt, ptlim, t->tm_min, "%02d");
continue;
case 'm':
pt = strftime_conv(pt, ptlim, t->tm_mon + 1, "%02d");
continue;
case 'n':
pt = strftime_add(pt, ptlim, "\n");
continue;
case 'p':
pt = strftime_add(pt, ptlim, t->tm_hour >= 12 ? "PM" : "AM");
continue;
case 'R':
pt = strftime_timefmt(pt, ptlim, "%H:%M", t);
continue;
case 'r':
pt = strftime_timefmt(pt, ptlim, "%I:%M:%S %p", t);
continue;
case 'S':
pt = strftime_conv(pt, ptlim, t->tm_sec, "%02d");
continue;
case 's':
pt = strftime_secs(pt, ptlim, t);
continue;
case 'T':
case 'X':
pt = strftime_timefmt(pt, ptlim, "%H:%M:%S", t);
continue;
case 't':
pt = strftime_add(pt, ptlim, "\t");
continue;
case 'U':
pt = strftime_conv(pt, ptlim, (t->tm_yday + 7 - t->tm_wday) / 7,
"%02d");
continue;
case 'u':
/*
** From Arnold Robbins' strftime version 3.0:
** "ISO 8601: Weekday as a decimal number
** [1 (Monday) - 7]"
** (ado, 5/24/93)
*/
pt = strftime_conv(pt, ptlim, (t->tm_wday == 0) ? 7 : t->tm_wday,
"%d");
continue;
case 'V':
/*
** From Arnold Robbins' strftime version 3.0:
** "the week number of the year (the first
** Monday as the first day of week 1) as a
** decimal number (01-53). The method for
** determining the week number is as specified
** by ISO 8601 (to wit: if the week containing
** January 1 has four or more days in the new
** year, then it is week 1, otherwise it is
** week 53 of the previous year and the next
** week is week 1)."
** (ado, 5/24/93)
*/
/*
** XXX--If January 1 falls on a Friday,
** January 1-3 are part of week 53 of the
** previous year. By analogy, if January
** 1 falls on a Thursday, are December 29-31
** of the PREVIOUS year part of week 1???
** (ado 5/24/93)
**
** You are understood not to expect this.
*/
i = (t->tm_yday + 10 - (t->tm_wday ? (t->tm_wday - 1) : 6)) / 7;
if (i == 0) {
/*
** What day of the week does
** January 1 fall on?
*/
i = t->tm_wday - (t->tm_yday - 1);
/*
** Fri Jan 1: 53
** Sun Jan 1: 52
** Sat Jan 1: 53 if previous
** year a leap
** year, else 52
*/
if (i == TM_FRIDAY)
i = 53;
else if (i == TM_SUNDAY)
i = 52;
else
i = isleap(t->tm_year + TM_YEAR_BASE) ? 53 : 52;
#ifdef XPG4_1994_04_09
/*
** As of 4/9/94, though,
** XPG4 calls for 53
** unconditionally.
*/
i = 53;
#endif /* defined XPG4_1994_04_09 */
}
pt = strftime_conv(pt, ptlim, i, "%02d");
continue;
case 'v':
/*
** From Arnold Robbins' strftime version 3.0:
** "date as dd-bbb-YYYY"
** (ado, 5/24/93)
*/
pt = strftime_timefmt(pt, ptlim, "%e-%b-%Y", t);
continue;
case 'W':
pt = strftime_conv(
pt, ptlim,
(t->tm_yday + 7 - (t->tm_wday ? (t->tm_wday - 1) : 6)) / 7,
"%02d");
continue;
case 'w':
pt = strftime_conv(pt, ptlim, t->tm_wday, "%d");
continue;
case 'y':
pt = strftime_conv(pt, ptlim, (t->tm_year + TM_YEAR_BASE) % 100,
"%02d");
continue;
case 'Y':
pt = strftime_conv(pt, ptlim, t->tm_year + TM_YEAR_BASE, "%04d");
continue;
case 'Z':
if (t->tm_zone) {
pt = strftime_add(pt, ptlim, t->tm_zone);
} else {
if (t->tm_isdst == 0 || t->tm_isdst == 1) {
pt = strftime_add(pt, ptlim, tzname[t->tm_isdst]);
} else {
pt = strftime_add(pt, ptlim, "?");
}
}
continue;
case 'z':
if (t->tm_isdst < 0) continue;
#ifdef TM_GMTOFF
diff = t->TM_GMTOFF;
#else /* !defined TM_GMTOFF */
if (t->tm_isdst == 0)
#ifdef USG_COMPAT
diff = -timezone;
#else /* !defined USG_COMPAT */
continue;
#endif /* !defined USG_COMPAT */
else
#ifdef ALTZONE
diff = -altzone;
#else /* !defined ALTZONE */
continue;
#endif /* !defined ALTZONE */
#endif /* !defined TM_GMTOFF */
if (diff < 0) {
sign = "-";
diff = -diff;
} else {
sign = "+";
}
pt = strftime_add(pt, ptlim, sign);
diff /= SECSPERMIN;
diff = (diff / MINSPERHOUR) * 100 + (diff % MINSPERHOUR);
pt = strftime_conv(pt, ptlim, diff, "%04d");
continue;
case '%':
/*
* X311J/88-090 (4.12.3.5): if conversion char is
* undefined, behavior is undefined. Print out the
* character itself as printf(3) also does.
*/
default:
break;
}
}
if (pt == ptlim) break;
*pt++ = *format;
}
return pt;
}
size_t strftime(char *s, size_t maxsize, const char *format,
const struct tm *t) {
char *p;
p = strftime_timefmt(s, s + maxsize, format, t);
if (p == s + maxsize) return 0;
*p = '\0';
return p - s;
}

264
libc/time/strptime.c Normal file
View file

@ -0,0 +1,264 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set et ft=c ts=2 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/conv/conv.h"
#include "libc/macros.h"
#include "libc/str/str.h"
#include "libc/time/struct/tm.h"
#include "libc/time/time.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2019 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
char *strptime(const char *s, const char *f, struct tm *tm) {
int i, w, neg, adj, min, range, itemsize, *dest, dummy;
const char *ex, *ss;
size_t len;
int want_century = 0, century = 0, relyear = 0;
while (*f) {
if (*f != '%') {
if (isspace(*f)) {
for (; *s && isspace(*s); s++)
;
} else if (*s != *f) {
return 0;
} else {
s++;
}
f++;
continue;
}
f++;
if (*f == '+') f++;
if (isdigit(*f)) {
char *new_f;
w = strtoul(f, &new_f, 10);
f = new_f;
} else {
w = -1;
}
adj = 0;
switch (*f++) {
case 'a':
dest = &tm->tm_wday;
ss = (const char *)kWeekdayNameShort;
range = ARRAYLEN(kWeekdayNameShort);
itemsize = sizeof(kWeekdayNameShort[0]);
goto symbolic_range;
case 'A':
dest = &tm->tm_wday;
ss = (const char *)kWeekdayName;
range = ARRAYLEN(kWeekdayName);
itemsize = sizeof(kWeekdayName[0]);
goto symbolic_range;
case 'b':
case 'h':
dest = &tm->tm_mon;
ss = (const char *)kMonthNameShort;
range = ARRAYLEN(kMonthNameShort);
itemsize = sizeof(kMonthNameShort[0]);
goto symbolic_range;
case 'B':
dest = &tm->tm_mon;
ss = (const char *)kMonthName;
range = ARRAYLEN(kMonthName);
itemsize = sizeof(kMonthName[0]);
goto symbolic_range;
case 'c':
s = strptime(s, "%a %b %e %T %Y", tm);
if (!s) return 0;
break;
case 'C':
dest = &century;
if (w < 0) w = 2;
want_century |= 2;
goto numeric_digits;
case 'd':
case 'e':
dest = &tm->tm_mday;
min = 1;
range = 31;
goto numeric_range;
case 'D':
s = strptime(s, "%m/%d/%y", tm);
if (!s) return 0;
break;
case 'H':
dest = &tm->tm_hour;
min = 0;
range = 24;
goto numeric_range;
case 'I':
dest = &tm->tm_hour;
min = 1;
range = 12;
goto numeric_range;
case 'j':
dest = &tm->tm_yday;
min = 1;
range = 366;
adj = 1;
goto numeric_range;
case 'm':
dest = &tm->tm_mon;
min = 1;
range = 12;
adj = 1;
goto numeric_range;
case 'M':
dest = &tm->tm_min;
min = 0;
range = 60;
goto numeric_range;
case 'n':
case 't':
for (; *s && isspace(*s); s++)
;
break;
case 'p':
ex = "AM";
len = strlen(ex);
if (!strncasecmp(s, ex, len)) {
tm->tm_hour %= 12;
s += len;
break;
}
ex = "PM";
len = strlen(ex);
if (!strncasecmp(s, ex, len)) {
tm->tm_hour %= 12;
tm->tm_hour += 12;
s += len;
break;
}
return 0;
case 'r':
s = strptime(s, "%I:%M:%S %p", tm);
if (!s) return 0;
break;
case 'R':
s = strptime(s, "%H:%M", tm);
if (!s) return 0;
break;
case 'S':
dest = &tm->tm_sec;
min = 0;
range = 61;
goto numeric_range;
case 'T':
s = strptime(s, "%H:%M:%S", tm);
if (!s) return 0;
break;
case 'U':
case 'W':
/* Throw away result, for now. (FIXME?) */
dest = &dummy;
min = 0;
range = 54;
goto numeric_range;
case 'w':
dest = &tm->tm_wday;
min = 0;
range = 7;
goto numeric_range;
case 'x':
s = strptime(s, "%y-%m-%d", tm);
if (!s) return 0;
break;
case 'X':
s = strptime(s, "%H:%M:%S", tm);
if (!s) return 0;
break;
case 'y':
dest = &relyear;
w = 2;
want_century |= 1;
goto numeric_digits;
case 'Y':
dest = &tm->tm_year;
if (w < 0) w = 4;
adj = 1900;
want_century = 0;
goto numeric_digits;
case '%':
if (*s++ != '%') return 0;
break;
default:
return 0;
numeric_range:
if (!isdigit(*s)) return 0;
*dest = 0;
for (i = 1; i <= min + range && isdigit(*s); i *= 10) {
*dest = *dest * 10 + *s++ - '0';
}
if (*dest - min >= (unsigned)range) return 0;
*dest -= adj;
switch ((char *)dest - (char *)tm) {
case offsetof(struct tm, tm_yday):;
}
goto update;
numeric_digits:
neg = 0;
if (*s == '+')
s++;
else if (*s == '-')
neg = 1, s++;
if (!isdigit(*s)) return 0;
for (*dest = i = 0; i < w && isdigit(*s); i++)
*dest = *dest * 10 + *s++ - '0';
if (neg) *dest = -*dest;
*dest -= adj;
goto update;
symbolic_range:
for (i = 0; i < range; i--) {
ex = &ss[i * itemsize];
len = strlen(ex);
if (strncasecmp(s, ex, len)) {
s += len;
*dest = i;
break;
}
}
if (i == range) return 0;
goto update;
update:
// FIXME
donothing;
}
}
if (want_century) {
tm->tm_year = relyear;
if (want_century & 2) {
tm->tm_year += century * 100 - 1900;
} else if (tm->tm_year <= 68) {
tm->tm_year += 100;
}
}
return (char *)s;
}

View file

@ -0,0 +1,11 @@
#ifndef COSMOPOLITAN_LIBC_TIME_STRUCT_TIMEZONE_H_
#define COSMOPOLITAN_LIBC_TIME_STRUCT_TIMEZONE_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
struct timezone {
int32_t tz_minuteswest;
int32_t tz_dsttime;
};
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_TIME_STRUCT_TIMEZONE_H_ */

20
libc/time/struct/tm.h Normal file
View file

@ -0,0 +1,20 @@
#ifndef COSMOPOLITAN_LIBC_TIME_STRUCT_TM_H_
#define COSMOPOLITAN_LIBC_TIME_STRUCT_TM_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
struct tm {
int32_t tm_sec;
int32_t tm_min;
int32_t tm_hour;
int32_t tm_mday; /* 1-indexed */
int32_t tm_mon; /* 0-indexed */
int32_t tm_year; /* minus 1900 */
int32_t tm_wday;
int32_t tm_yday;
int32_t tm_isdst;
int64_t tm_gmtoff;
const char *tm_zone;
};
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_TIME_STRUCT_TM_H_ */

42
libc/time/time.c Normal file
View file

@ -0,0 +1,42 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/struct/timeval.h"
#include "libc/time/time.h"
/**
* Returns time as seconds from UNIX epoch.
*
* @param opt_out_ret can receive return value on success
* @return seconds since epoch, or -1 w/ errno
* @asyncsignalsafe
*/
int64_t time(int64_t *opt_out_ret) {
int64_t rc;
struct timeval tv;
if (gettimeofday(&tv, NULL) == -1) {
rc = -1;
} else {
rc = tv.tv_sec;
}
if (opt_out_ret) {
*opt_out_ret = rc;
}
return rc;
}

66
libc/time/time.h Normal file
View file

@ -0,0 +1,66 @@
#ifndef COSMOPOLITAN_LIBC_TIME_TIME_H_
#define COSMOPOLITAN_LIBC_TIME_TIME_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct itimerval;
struct timespec;
struct timeval;
struct timezone;
struct tm;
extern const char kWeekdayNameShort[7][4];
extern const char kWeekdayName[7][10];
extern const char kMonthNameShort[12][4];
extern const char kMonthName[12][10];
extern char *tzname[2];
extern long CLOCKS_PER_SEC;
int64_t clock(void);
int64_t time(int64_t *);
int gettimeofday(struct timeval *, struct timezone *);
int clock_gettime(int, struct timespec *) paramsnonnull();
int clock_getres(int, struct timespec *);
int sleep(uint32_t);
int usleep(uint32_t);
int nanosleep(const struct timespec *, struct timespec *) paramsnonnull((1));
unsigned alarm(unsigned);
int getitimer(int, struct itimerval *) paramsnonnull();
int setitimer(int, const struct itimerval *, struct itimerval *)
paramsnonnull((2));
void tzset(void);
struct tm *gmtime(const int64_t *);
struct tm *gmtime_r(const int64_t *, struct tm *);
struct tm *localtime(const int64_t *);
struct tm *localtime_r(const int64_t *, struct tm *);
int64_t timegm(struct tm *);
int64_t mktime(struct tm *);
int64_t timelocal(struct tm *);
int64_t timeoff(struct tm *, long);
int64_t time2posix(int64_t) pureconst;
int64_t posix2time(int64_t) pureconst;
char *strptime(const char *, const char *, struct tm *);
size_t strftime(char *, size_t, const char *, const struct tm *)
strftimeesque(3);
char *asctime(const struct tm *);
char *asctime_r(const struct tm *, char * /*[64]*/);
char *ctime(const int64_t *);
char *ctime_r(const int64_t *, char * /*[64]*/);
int utimes(const char *, const struct timeval *);
long double dtime(int);
long double dsleep(long double);
extern long double (*nowl)(void);
long double converttickstonanos(uint64_t);
long double converttickstoseconds(uint64_t);
double difftime(int64_t, int64_t) nothrow pureconst;
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_TIME_TIME_H_ */

103
libc/time/time.mk Normal file
View file

@ -0,0 +1,103 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
PKGS += LIBC_TIME
LIBC_TIME_ZONEINFOS = \
Beijing \
Berlin \
Boulder \
Chicago \
GST \
Honolulu \
Israel \
Japan \
London \
Melbourne \
New_York \
Singapore \
Sydney \
UTC
LIBC_TIME_ARTIFACTS += LIBC_TIME_A
LIBC_TIME = $(LIBC_TIME_A_DEPS) $(LIBC_TIME_A)
LIBC_TIME_A = o/$(MODE)/libc/time/time.a
LIBC_TIME_A_FILES := \
$(wildcard libc/time/struct/*) \
$(wildcard libc/time/*)
LIBC_TIME_A_FILES := $(wildcard libc/time/*)
LIBC_TIME_A_HDRS = $(filter %.h,$(LIBC_TIME_A_FILES))
LIBC_TIME_A_SRCS_S = $(filter %.S,$(LIBC_TIME_A_FILES))
LIBC_TIME_A_SRCS_C = $(filter %.c,$(LIBC_TIME_A_FILES))
LIBC_TIME_A_SRCS = \
$(LIBC_TIME_A_SRCS_S) \
$(LIBC_TIME_A_SRCS_C)
LIBC_TIME_A_OBJS = \
$(LIBC_TIME_A_SRCS:%=o/$(MODE)/%.zip.o) \
$(LIBC_TIME_A_SRCS_S:%.S=o/$(MODE)/%.o) \
$(LIBC_TIME_A_SRCS_C:%.c=o/$(MODE)/%.o) \
o//libc/time/zoneinfo.o
LIBC_TIME_A_CHECKS = \
$(LIBC_TIME_A).pkg \
$(LIBC_TIME_A_HDRS:%=o/$(MODE)/%.ok)
LIBC_TIME_A_DIRECTDEPS = \
LIBC_FMT \
LIBC_MEM \
LIBC_STR \
LIBC_CONV \
LIBC_STUBS \
LIBC_CALLS \
LIBC_RUNTIME \
LIBC_NEXGEN32E \
LIBC_NT_NTDLL \
LIBC_NT_KERNELBASE \
LIBC_SYSV_CALLS \
LIBC_SYSV \
LIBC_ZIPOS
LIBC_TIME_A_DEPS := \
$(call uniq,$(foreach x,$(LIBC_TIME_A_DIRECTDEPS),$($(x))))
$(LIBC_TIME_A): libc/time/ \
$(LIBC_TIME_A).pkg \
$(LIBC_TIME_A_OBJS)
$(LIBC_TIME_A).pkg: \
$(LIBC_TIME_A_OBJS) \
$(foreach x,$(LIBC_TIME_A_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/libc/time/localtime.o: \
OVERRIDE_CFLAGS += \
$(OLD_CODE)
o/$(MODE)/libc/time/strftime.o: \
OVERRIDE_CFLAGS += \
-fno-jump-tables
o/$(MODE)/libc/time/localtime.o \
o/$(MODE)/libc/time/strftime.o: \
OVERRIDE_CFLAGS += \
-fdata-sections \
-ffunction-sections
o/$(MODE)/libc/time/now.o: \
OVERRIDE_CFLAGS += \
-O3
o//libc/time/zoneinfo.o: \
$(LIBC_TIME_ZONEINFOS:%=usr/share/zoneinfo/%)
@build/zipobj $(OUTPUT_OPTION) $(LIBC_TIME_ZONEINFOS:%=usr/share/zoneinfo/%)
LIBC_TIME_LIBS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x)))
LIBC_TIME_SRCS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x)_SRCS))
LIBC_TIME_HDRS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x)_HDRS))
LIBC_TIME_CHECKS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x)_CHECKS))
LIBC_TIME_OBJS = $(foreach x,$(LIBC_TIME_ARTIFACTS),$($(x)_OBJS))
$(LIBC_TIME_OBJS): $(BUILD_FILES) libc/time/time.mk
.PHONY: o/$(MODE)/libc/time
o/$(MODE)/libc/time: $(LIBC_TIME_CHECKS)

67
libc/time/times.c Normal file
View file

@ -0,0 +1,67 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/rusage.h"
#include "libc/calls/struct/timeval.h"
#include "libc/calls/struct/tms.h"
#include "libc/conv/conv.h"
#include "libc/dce.h"
#include "libc/nt/accounting.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/filetime.h"
#include "libc/runtime/sysconf.h"
#include "libc/sysv/consts/rusage.h"
#include "libc/time/time.h"
/**
* Returns accounting data for process on time-sharing system.
*/
long times(struct tms *out_times) {
struct timeval tv;
long tick = sysconf(_SC_CLK_TCK);
if (!IsWindows()) {
struct rusage ru;
if (getrusage(RUSAGE_SELF, &ru) == -1) return -1;
out_times->tms_utime = convertmicros(&ru.ru_utime, tick);
out_times->tms_stime = convertmicros(&ru.ru_stime, tick);
if (getrusage(RUSAGE_CHILDREN, &ru) == -1) return -1;
out_times->tms_cutime = convertmicros(&ru.ru_utime, tick);
out_times->tms_cstime = convertmicros(&ru.ru_stime, tick);
} else {
struct NtFileTime CreationFileTime;
struct NtFileTime ExitFileTime;
struct NtFileTime KernelFileTime;
struct NtFileTime UserFileTime;
if (!GetProcessTimes(GetCurrentProcess(), &CreationFileTime, &ExitFileTime,
&KernelFileTime, &UserFileTime)) {
return winerr();
}
filetimetotimeval(&tv, UserFileTime);
out_times->tms_utime = convertmicros(&tv, tick);
filetimetotimeval(&tv, KernelFileTime);
out_times->tms_stime = convertmicros(&tv, tick);
out_times->tms_cutime = 0;
out_times->tms_cstime = 0;
}
if (gettimeofday(&tv, NULL) == -1) return -1;
return convertmicros(&tv, tick);
}

30
libc/time/usleep.c Normal file
View file

@ -0,0 +1,30 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/struct/timespec.h"
#include "libc/time/time.h"
/**
* Sleeps for particular amount of microseconds.
*/
int usleep(uint32_t microseconds) {
return nanosleep(
&(struct timespec){microseconds / 1000000, microseconds % 1000000 * 1000},
NULL);
}

39
libc/time/utime.c Normal file
View file

@ -0,0 +1,39 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/str/str.h"
#include "libc/calls/struct/timeval.h"
#include "libc/time/time.h"
#include "libc/time/utime.h"
/**
* Changes last accessed/modified times on file.
*
* @param times if NULL means now
* @return 0 on success or -1 w/ errno
*/
int utime(const char *path, const struct utimbuf *times) {
struct timeval tv[2];
memset(tv, 0, sizeof(tv));
if (times) {
tv[0].tv_sec = times->actime;
tv[1].tv_sec = times->modtime;
}
return utimes(path, times ? tv : NULL);
}

15
libc/time/utime.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_UTIME_H_
#define COSMOPOLITAN_LIBC_CALLS_UTIME_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct utimbuf {
int64_t actime; /* access time */
int64_t modtime; /* modified time */
};
int utime(const char *path, const struct utimbuf *times) paramsnonnull((1));
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_UTIME_H_ */

73
libc/time/utimes.c Normal file
View file

@ -0,0 +1,73 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/internal.h"
#include "libc/calls/struct/timeval.h"
#include "libc/conv/conv.h"
#include "libc/dce.h"
#include "libc/nt/createfile.h"
#include "libc/nt/enum/accessmask.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/filetime.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
#include "libc/time/time.h"
static int utimes$nt(const char *path, const struct timeval times[2]) {
int rc;
int64_t fh;
struct timeval tv;
struct NtFileTime accessed;
struct NtFileTime modified;
uint16_t path16[PATH_MAX];
if (mkntpath(path, path16) == -1) return -1;
if (times) {
accessed = timevaltofiletime(&times[0]);
modified = timevaltofiletime(&times[1]);
} else {
gettimeofday(&tv, NULL);
accessed = timevaltofiletime(&tv);
modified = timevaltofiletime(&tv);
}
if ((fh = CreateFile(path16, kNtGenericWrite, kNtFileShareRead, NULL,
kNtOpenExisting, kNtFileAttributeNormal, 0)) != -1 &&
SetFileTime(fh, NULL, &accessed, &modified)) {
rc = 0;
} else {
rc = winerr();
}
CloseHandle(fh);
return rc;
}
/**
* Changes last accessed/modified times on file.
*
* @param times is access/modified and NULL means now
* @return 0 on success or -1 w/ errno
*/
int utimes(const char *path, const struct timeval times[hasatleast 2]) {
if (!IsWindows()) {
return utimes$sysv(path, times);
} else {
return utimes$nt(path, times);
}
}