mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 11:37:35 +00:00
6f7d0cb1c3
This makes breaking changes to add underscores to many non-standard function names provided by the c library. MODE=tiny is now tinier and we now use smaller locks that are better for tiny apps in this mode. Some headers have been renamed to be in the same folder as the build package, so it'll be easier to know which build dependency is needed. Certain old misguided interfaces have been removed. Intel intrinsics headers are now listed in libc/isystem (but not in the amalgamation) to help further improve open source compatibility. Header complexity has also been reduced. Lastly, more shell scripts are now available.
319 lines
7.6 KiB
C
319 lines
7.6 KiB
C
#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/calls/calls.h"
|
|
#include "libc/calls/struct/sigaction.h"
|
|
#include "libc/errno.h"
|
|
#include "libc/fmt/conv.h"
|
|
#include "libc/intrin/bits.h"
|
|
#include "libc/log/check.h"
|
|
#include "libc/log/log.h"
|
|
#include "libc/macros.internal.h"
|
|
#include "libc/mem/mem.h"
|
|
#include "libc/nexgen32e/x86feature.h"
|
|
#include "libc/nt/runtime.h"
|
|
#include "libc/runtime/runtime.h"
|
|
#include "libc/stdio/rand.h"
|
|
#include "libc/stdio/stdio.h"
|
|
#include "libc/stdio/xorshift.h"
|
|
#include "libc/str/str.h"
|
|
#include "libc/sysv/consts/ex.h"
|
|
#include "libc/sysv/consts/exit.h"
|
|
#include "libc/sysv/consts/grnd.h"
|
|
#include "libc/sysv/consts/sig.h"
|
|
#include "libc/testlib/hyperion.h"
|
|
#include "third_party/getopt/getopt.h"
|
|
|
|
#define B 4096
|
|
|
|
bool isdone;
|
|
bool isbinary;
|
|
unsigned long count = -1;
|
|
|
|
uint64_t bcast(uint64_t f(void)) {
|
|
unsigned i;
|
|
uint64_t x;
|
|
for (x = i = 0; i < 8; ++i) {
|
|
x <<= 8;
|
|
x |= f() & 255;
|
|
}
|
|
return x;
|
|
}
|
|
|
|
uint64_t randv6(void) {
|
|
static int16_t gorp;
|
|
gorp = (gorp + 625) & 077777;
|
|
return gorp;
|
|
}
|
|
|
|
uint64_t randv7(void) {
|
|
static uint32_t randx = 1;
|
|
return ((randx = randx * 1103515245 + 12345) >> 16) & 077777;
|
|
}
|
|
|
|
uint64_t zero(void) {
|
|
return 0;
|
|
}
|
|
|
|
uint64_t inc(void) {
|
|
static uint64_t x;
|
|
return x++;
|
|
}
|
|
|
|
uint64_t unixv6(void) {
|
|
return bcast(randv6);
|
|
}
|
|
|
|
uint64_t unixv7(void) {
|
|
return bcast(randv7);
|
|
}
|
|
|
|
uint64_t ape(void) {
|
|
static int i;
|
|
if ((i += 8) > _end - _base) i = 8;
|
|
return READ64LE(_base + i);
|
|
}
|
|
|
|
uint64_t moby(void) {
|
|
static int i;
|
|
if ((i += 8) > kMobySize) i = 8;
|
|
return READ64LE(kMoby + i);
|
|
}
|
|
|
|
uint64_t knuth(void) {
|
|
uint64_t a, b;
|
|
static uint64_t x = 1;
|
|
x *= 6364136223846793005;
|
|
x += 1442695040888963407;
|
|
a = x >> 32;
|
|
x *= 6364136223846793005;
|
|
x += 1442695040888963407;
|
|
b = x >> 32;
|
|
return a | b << 32;
|
|
}
|
|
|
|
uint64_t rngset64(void) {
|
|
static unsigned i;
|
|
static uint64_t s;
|
|
if (!i) {
|
|
s = rand64();
|
|
i = (s + 1) & (511);
|
|
}
|
|
return MarsagliaXorshift64(&s);
|
|
}
|
|
|
|
uint64_t xorshift64(void) {
|
|
static uint64_t s = kMarsagliaXorshift64Seed;
|
|
return MarsagliaXorshift64(&s);
|
|
}
|
|
|
|
uint64_t xorshift32(void) {
|
|
static uint32_t s = kMarsagliaXorshift32Seed;
|
|
uint64_t a = MarsagliaXorshift32(&s);
|
|
uint64_t b = MarsagliaXorshift32(&s);
|
|
return (uint64_t)a << 32 | b;
|
|
}
|
|
|
|
uint64_t libc(void) {
|
|
uint64_t x;
|
|
CHECK_EQ(8, getrandom(&x, 8, 0));
|
|
return x;
|
|
}
|
|
|
|
uint64_t GetRandom(void) {
|
|
uint64_t x;
|
|
CHECK_EQ(8, getrandom(&x, 8, 0));
|
|
return x;
|
|
}
|
|
|
|
uint32_t python(void) {
|
|
#define K 0 // 624 /* wut */
|
|
#define N 624
|
|
#define M 397
|
|
static int index;
|
|
static char once;
|
|
static uint32_t mt[N];
|
|
static const uint32_t mag01[2] = {0, 0x9908b0dfu};
|
|
uint32_t y;
|
|
int kk;
|
|
if (!once) {
|
|
char *sp;
|
|
ssize_t rc;
|
|
uint32_t i, j, k, s[K];
|
|
mt[0] = 19650218;
|
|
for (i = 1; i < N; i++) {
|
|
mt[i] = (1812433253u * (mt[i - 1] ^ (mt[i - 1] >> 30)) + i);
|
|
}
|
|
if (K) {
|
|
for (sp = (char *)s, i = 0; i < sizeof(s); i += rc) {
|
|
if ((rc = getrandom(sp + i, sizeof(s) - i, 0)) == -1) {
|
|
if (errno != EINTR) abort();
|
|
}
|
|
}
|
|
for (i = 1, j = 0, k = MAX(N, K); k; k--) {
|
|
mt[i] =
|
|
(mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525u)) + s[j] + j;
|
|
if (++i >= N) mt[0] = mt[N - 1], i = 1;
|
|
if (++j >= K) j = 0;
|
|
}
|
|
for (k = N - 1; k; k--) {
|
|
mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1566083941u)) - i;
|
|
if (++i >= N) mt[0] = mt[N - 1], i = 1;
|
|
}
|
|
mt[0] = 0x80000000;
|
|
explicit_bzero(s, sizeof(s));
|
|
}
|
|
once = 1;
|
|
}
|
|
if (index >= N) {
|
|
for (kk = 0; kk < N - M; kk++) {
|
|
y = (mt[kk] & 0x80000000u) | (mt[kk + 1] & 0x7fffffff);
|
|
mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 1];
|
|
}
|
|
for (; kk < N - 1; kk++) {
|
|
y = (mt[kk] & 0x80000000u) | (mt[kk + 1] & 0x7fffffff);
|
|
mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 1];
|
|
}
|
|
y = (mt[N - 1] & 0x80000000u) | (mt[0] & 0x7fffffffu);
|
|
mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 1];
|
|
index = 0;
|
|
}
|
|
y = mt[index++];
|
|
y ^= y >> 11;
|
|
y ^= (y << 7) & 0x9d2c5680u;
|
|
y ^= (y << 15) & 0xefc60000u;
|
|
y ^= y >> 18;
|
|
return y;
|
|
#undef M
|
|
#undef N
|
|
#undef K
|
|
}
|
|
|
|
uint64_t pythonx2(void) {
|
|
uint64_t x = python();
|
|
x <<= 32;
|
|
x |= python();
|
|
return x;
|
|
}
|
|
|
|
const struct Function {
|
|
const char *s;
|
|
uint64_t (*f)(void);
|
|
} kFunctions[] = {
|
|
{"ape", ape}, //
|
|
{"getrandom", GetRandom}, //
|
|
{"inc", inc}, //
|
|
{"knuth", knuth}, //
|
|
{"lemur64", lemur64}, //
|
|
{"libc", libc}, //
|
|
{"moby", moby}, //
|
|
{"mt19937", _mt19937}, //
|
|
{"python", pythonx2}, //
|
|
{"rand64", rand64}, //
|
|
{"rdrand", rdrand}, //
|
|
{"rdrnd", rdrand}, //
|
|
{"rdseed", rdseed}, //
|
|
{"rngset64", rngset64}, //
|
|
{"unixv6", unixv6}, //
|
|
{"unixv7", unixv7}, //
|
|
{"vigna", vigna}, //
|
|
{"xorshift32", xorshift32}, //
|
|
{"xorshift64", xorshift64}, //
|
|
{"zero", zero}, //
|
|
};
|
|
|
|
void OnInt(int sig) {
|
|
isdone = true;
|
|
}
|
|
|
|
wontreturn void PrintUsage(FILE *f, int rc) {
|
|
fprintf(f, "Usage: %s [-b] [-n NUM] [FUNC]\n", program_invocation_name);
|
|
exit(rc);
|
|
}
|
|
|
|
int main(int argc, char *argv[]) {
|
|
char *p;
|
|
int i, opt;
|
|
ssize_t rc;
|
|
uint64_t x;
|
|
static char buf[B];
|
|
uint64_t (*f)(void);
|
|
|
|
while ((opt = getopt(argc, argv, "hbc:n:")) != -1) {
|
|
switch (opt) {
|
|
case 'b':
|
|
isbinary = true;
|
|
break;
|
|
case 'c':
|
|
case 'n':
|
|
count = sizetol(optarg, 1024);
|
|
break;
|
|
case 'h':
|
|
PrintUsage(stdout, EXIT_SUCCESS);
|
|
default:
|
|
PrintUsage(stderr, EX_USAGE);
|
|
}
|
|
}
|
|
|
|
if (optind == argc) {
|
|
f = libc;
|
|
} else {
|
|
for (f = 0, i = 0; i < ARRAYLEN(kFunctions); ++i) {
|
|
if (!strcasecmp(argv[optind], kFunctions[i].s)) {
|
|
f = kFunctions[i].f;
|
|
break;
|
|
}
|
|
}
|
|
if (!f) {
|
|
fprintf(stderr, "unknown function: %`'s\n", argv[optind]);
|
|
fprintf(stderr, "try: ");
|
|
for (i = 0; i < ARRAYLEN(kFunctions); ++i) {
|
|
if (i) fprintf(stderr, ", ");
|
|
fprintf(stderr, "%s", kFunctions[i].s);
|
|
}
|
|
fprintf(stderr, "\n");
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
signal(SIGINT, OnInt);
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
if (!isbinary) {
|
|
for (; count && !isdone && !feof(stdout); --count) {
|
|
printf("0x%016lx\n", f());
|
|
}
|
|
fflush(stdout);
|
|
return ferror(stdout) ? 1 : 0;
|
|
}
|
|
|
|
while (count && !isdone) {
|
|
if (count >= B) {
|
|
for (i = 0; i < B / 8; ++i) {
|
|
x = f();
|
|
p = buf + i * 8;
|
|
WRITE64LE(p, x);
|
|
}
|
|
for (i = 0; i < B; i += rc) {
|
|
rc = write(1, buf + i, B - i);
|
|
if (rc == -1 && errno == EPIPE) exit(1);
|
|
if (rc == -1) perror("write"), exit(1);
|
|
}
|
|
} else {
|
|
x = f();
|
|
rc = write(1, &x, MIN(8, count));
|
|
}
|
|
if (!rc) break;
|
|
if (rc == -1 && errno == EPIPE) exit(1);
|
|
if (rc == -1) perror("write"), exit(1);
|
|
count -= rc;
|
|
}
|
|
|
|
return 0;
|
|
}
|