mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
5029e20bef
Some progress has been made on introducing completion but there's been difficulties using the Python C API to get local shell variables.
291 lines
6.6 KiB
C
291 lines
6.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/bits/bits.h"
|
|
#include "libc/calls/calls.h"
|
|
#include "libc/errno.h"
|
|
#include "libc/fmt/conv.h"
|
|
#include "libc/log/check.h"
|
|
#include "libc/log/log.h"
|
|
#include "libc/macros.internal.h"
|
|
#include "libc/nexgen32e/x86feature.h"
|
|
#include "libc/rand/rand.h"
|
|
#include "libc/rand/xorshift.h"
|
|
#include "libc/stdio/stdio.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 vigna(void) {
|
|
static uint64_t x;
|
|
uint64_t z = (x += 0x9e3779b97f4a7c15);
|
|
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
|
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
|
return z ^ (z >> 31);
|
|
}
|
|
|
|
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 kernel(void) {
|
|
uint64_t x;
|
|
CHECK_EQ(8, getrandom(&x, 8, GRND_NORDRND));
|
|
return x;
|
|
}
|
|
|
|
uint64_t hardware(void) {
|
|
uint64_t x;
|
|
CHECK_EQ(8, getrandom(&x, 8, GRND_NOSYSTEM));
|
|
return x;
|
|
}
|
|
|
|
uint64_t rdrnd(void) {
|
|
char cf;
|
|
int i = 0;
|
|
uint64_t x;
|
|
CHECK(X86_HAVE(RDRND));
|
|
for (;;) {
|
|
asm volatile(CFLAG_ASM("rdrand\t%1")
|
|
: CFLAG_CONSTRAINT(cf), "=r"(x)
|
|
: /* no inputs */
|
|
: "cc");
|
|
if (cf) return x;
|
|
if (++i < 10) continue;
|
|
asm volatile("pause");
|
|
i = 0;
|
|
}
|
|
}
|
|
|
|
uint64_t rdseed(void) {
|
|
char cf;
|
|
int i = 0;
|
|
uint64_t x;
|
|
CHECK(X86_HAVE(RDSEED));
|
|
for (;;) {
|
|
asm volatile(CFLAG_ASM("rdseed\t%1")
|
|
: CFLAG_CONSTRAINT(cf), "=r"(x)
|
|
: /* no inputs */
|
|
: "cc");
|
|
if (cf) return x;
|
|
if (++i < 10) continue;
|
|
asm volatile("pause");
|
|
i = 0;
|
|
}
|
|
}
|
|
|
|
const struct Function {
|
|
const char *s;
|
|
uint64_t (*f)(void);
|
|
} kFunctions[] = {
|
|
{"ape", ape}, //
|
|
{"hardware", hardware}, //
|
|
{"inc", inc}, //
|
|
{"kernel", kernel}, //
|
|
{"knuth", knuth}, //
|
|
{"libc", libc}, //
|
|
{"moby", moby}, //
|
|
{"rand64", rand64}, //
|
|
{"rdrand", rdrnd}, //
|
|
{"rdrnd", rdrnd}, //
|
|
{"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 = strtoul(optarg, 0, 0);
|
|
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;
|
|
}
|