mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 05:42:29 +00:00
Improve linenoise and get it working on Windows
Some progress has been made on introducing completion but there's been difficulties using the Python C API to get local shell variables.
This commit is contained in:
parent
968474d291
commit
5029e20bef
23 changed files with 408 additions and 209 deletions
|
@ -16,6 +16,7 @@
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/nexgen32e/x86feature.h"
|
#include "libc/nexgen32e/x86feature.h"
|
||||||
#include "libc/rand/rand.h"
|
#include "libc/rand/rand.h"
|
||||||
|
#include "libc/rand/xorshift.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/ex.h"
|
#include "libc/sysv/consts/ex.h"
|
||||||
|
@ -25,6 +26,12 @@
|
||||||
#include "libc/testlib/hyperion.h"
|
#include "libc/testlib/hyperion.h"
|
||||||
#include "third_party/getopt/getopt.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)) {
|
uint64_t bcast(uint64_t f(void)) {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
uint64_t x;
|
uint64_t x;
|
||||||
|
@ -95,6 +102,28 @@ uint64_t vigna(void) {
|
||||||
return z ^ (z >> 31);
|
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 libc(void) {
|
||||||
uint64_t x;
|
uint64_t x;
|
||||||
CHECK_EQ(8, getrandom(&x, 8, 0));
|
CHECK_EQ(8, getrandom(&x, 8, 0));
|
||||||
|
@ -151,27 +180,26 @@ const struct Function {
|
||||||
const char *s;
|
const char *s;
|
||||||
uint64_t (*f)(void);
|
uint64_t (*f)(void);
|
||||||
} kFunctions[] = {
|
} kFunctions[] = {
|
||||||
{"ape", ape}, //
|
{"ape", ape}, //
|
||||||
{"hardware", hardware}, //
|
{"hardware", hardware}, //
|
||||||
{"inc", inc}, //
|
{"inc", inc}, //
|
||||||
{"kernel", kernel}, //
|
{"kernel", kernel}, //
|
||||||
{"knuth", knuth}, //
|
{"knuth", knuth}, //
|
||||||
{"libc", libc}, //
|
{"libc", libc}, //
|
||||||
{"moby", moby}, //
|
{"moby", moby}, //
|
||||||
{"rand64", rand64}, //
|
{"rand64", rand64}, //
|
||||||
{"rdrand", rdrnd}, //
|
{"rdrand", rdrnd}, //
|
||||||
{"rdrnd", rdrnd}, //
|
{"rdrnd", rdrnd}, //
|
||||||
{"rdseed", rdseed}, //
|
{"rdseed", rdseed}, //
|
||||||
{"unixv6", unixv6}, //
|
{"rngset64", rngset64}, //
|
||||||
{"unixv7", unixv7}, //
|
{"unixv6", unixv6}, //
|
||||||
{"vigna", vigna}, //
|
{"unixv7", unixv7}, //
|
||||||
{"zero", zero}, //
|
{"vigna", vigna}, //
|
||||||
|
{"xorshift32", xorshift32}, //
|
||||||
|
{"xorshift64", xorshift64}, //
|
||||||
|
{"zero", zero}, //
|
||||||
};
|
};
|
||||||
|
|
||||||
bool isdone;
|
|
||||||
bool isbinary;
|
|
||||||
unsigned long count = -1;
|
|
||||||
|
|
||||||
void OnInt(int sig) {
|
void OnInt(int sig) {
|
||||||
isdone = true;
|
isdone = true;
|
||||||
}
|
}
|
||||||
|
@ -182,16 +210,19 @@ wontreturn void PrintUsage(FILE *f, int rc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
char *p;
|
||||||
int i, opt;
|
int i, opt;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
uint64_t x;
|
uint64_t x;
|
||||||
|
static char buf[B];
|
||||||
uint64_t (*f)(void);
|
uint64_t (*f)(void);
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "hbn:")) != -1) {
|
while ((opt = getopt(argc, argv, "hbc:n:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'b':
|
case 'b':
|
||||||
isbinary = true;
|
isbinary = true;
|
||||||
break;
|
break;
|
||||||
|
case 'c':
|
||||||
case 'n':
|
case 'n':
|
||||||
count = strtoul(optarg, 0, 0);
|
count = strtoul(optarg, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
@ -235,10 +266,23 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (count && !isdone) {
|
while (count && !isdone) {
|
||||||
x = f();
|
if (count >= B) {
|
||||||
rc = write(1, &x, MIN(8, count));
|
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) break;
|
||||||
if (rc == -1 && errno == EPIPE) return 1;
|
if (rc == -1 && errno == EPIPE) exit(1);
|
||||||
if (rc == -1) perror("write"), exit(1);
|
if (rc == -1) perror("write"), exit(1);
|
||||||
count -= rc;
|
count -= rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -267,8 +267,12 @@ int editorReadKey(int64_t fd) {
|
||||||
if (read(fd, seq + 2, 1) == 0) return CTRL('[');
|
if (read(fd, seq + 2, 1) == 0) return CTRL('[');
|
||||||
if (seq[2] == '~') {
|
if (seq[2] == '~') {
|
||||||
switch (seq[1]) {
|
switch (seq[1]) {
|
||||||
|
case '1':
|
||||||
|
return HOME_KEY;
|
||||||
case '3':
|
case '3':
|
||||||
return DEL_KEY;
|
return DEL_KEY;
|
||||||
|
case '4':
|
||||||
|
return END_KEY;
|
||||||
case '5':
|
case '5':
|
||||||
return PAGE_UP;
|
return PAGE_UP;
|
||||||
case '6':
|
case '6':
|
||||||
|
|
|
@ -41,7 +41,8 @@ textwindows int ioctl_tcgets_nt(int ignored, struct termios *tio) {
|
||||||
if (inmode & kNtEnableProcessedInput) tio->c_lflag |= IEXTEN | ISIG;
|
if (inmode & kNtEnableProcessedInput) tio->c_lflag |= IEXTEN | ISIG;
|
||||||
}
|
}
|
||||||
if (outok) {
|
if (outok) {
|
||||||
if (inmode & kNtEnableProcessedInput) tio->c_lflag |= IEXTEN | ISIG;
|
if (outmode & kNtEnableProcessedOutput) tio->c_oflag |= OPOST;
|
||||||
|
if (!(outmode & kNtDisableNewlineAutoReturn)) tio->c_oflag |= ONLCR;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -51,8 +51,8 @@ textwindows int ioctl_tcsets_nt(int ignored, uint64_t request,
|
||||||
}
|
}
|
||||||
if (outok) {
|
if (outok) {
|
||||||
outmode |= kNtEnableWrapAtEolOutput;
|
outmode |= kNtEnableWrapAtEolOutput;
|
||||||
outmode |= kNtEnableProcessedOutput;
|
if (tio->c_oflag & OPOST) outmode |= kNtEnableProcessedOutput;
|
||||||
if (!(tio->c_oflag & OPOST)) outmode |= kNtDisableNewlineAutoReturn;
|
if (!(tio->c_oflag & ONLCR)) outmode |= kNtDisableNewlineAutoReturn;
|
||||||
if (NtGetVersion() >= kNtVersionWindows10) {
|
if (NtGetVersion() >= kNtVersionWindows10) {
|
||||||
outmode |= kNtEnableVirtualTerminalProcessing;
|
outmode |= kNtEnableVirtualTerminalProcessing;
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,7 @@ ssize_t readansi(int fd, char *buf, size_t size) {
|
||||||
break;
|
break;
|
||||||
case kCsi:
|
case kCsi:
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
case '[':
|
||||||
case ':':
|
case ':':
|
||||||
case ';':
|
case ';':
|
||||||
case '<':
|
case '<':
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "libc/bits/bits.h"
|
#include "libc/bits/bits.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/log/backtrace.internal.h"
|
#include "libc/log/backtrace.internal.h"
|
||||||
|
#include "libc/log/internal.h"
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,6 +30,7 @@
|
||||||
relegated wontreturn void __die(void) {
|
relegated wontreturn void __die(void) {
|
||||||
static bool once;
|
static bool once;
|
||||||
if (cmpxchg(&once, false, true)) {
|
if (cmpxchg(&once, false, true)) {
|
||||||
|
__restore_tty();
|
||||||
if (IsDebuggerPresent(false)) DebugBreak();
|
if (IsDebuggerPresent(false)) DebugBreak();
|
||||||
ShowBacktrace(2, NULL);
|
ShowBacktrace(2, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,16 +2,19 @@
|
||||||
#define COSMOPOLITAN_LIBC_LOG_INTERNAL_H_
|
#define COSMOPOLITAN_LIBC_LOG_INTERNAL_H_
|
||||||
#include "libc/calls/struct/sigaction.h"
|
#include "libc/calls/struct/sigaction.h"
|
||||||
#include "libc/calls/struct/siginfo.h"
|
#include "libc/calls/struct/siginfo.h"
|
||||||
|
#include "libc/calls/struct/termios.h"
|
||||||
#include "libc/calls/ucontext.h"
|
#include "libc/calls/ucontext.h"
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
extern int kCrashSigs[8] hidden;
|
extern int kCrashSigs[8] hidden;
|
||||||
|
extern struct termios g_oldtermios hidden;
|
||||||
extern struct sigaction g_oldcrashacts[8] hidden;
|
extern struct sigaction g_oldcrashacts[8] hidden;
|
||||||
|
|
||||||
void __start_fatal(const char *, int) hidden;
|
void __start_fatal(const char *, int) hidden;
|
||||||
void __start_fatal_ndebug(void) hidden;
|
void __start_fatal_ndebug(void) hidden;
|
||||||
void __oncrash(int, struct siginfo *, struct ucontext *) relegated;
|
void __oncrash(int, struct siginfo *, struct ucontext *) relegated;
|
||||||
|
void __restore_tty(void);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
45
libc/log/oldtermios.c
Normal file
45
libc/log/oldtermios.c
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
/*-*- 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 2021 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/termios.h"
|
||||||
|
#include "libc/log/internal.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
|
#define SHOW_CURSOR "\e[?25h"
|
||||||
|
#define DISABLE_MOUSE "\e[?1000;1002;1015;1006l"
|
||||||
|
#define ANSI_RESTORE SHOW_CURSOR DISABLE_MOUSE
|
||||||
|
|
||||||
|
struct termios g_oldtermios;
|
||||||
|
|
||||||
|
static textstartup void g_oldtermios_init() {
|
||||||
|
if (isatty(1)) {
|
||||||
|
tcgetattr(1, &g_oldtermios);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const void *const g_oldtermios_ctor[] initarray = {
|
||||||
|
g_oldtermios_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
void __restore_tty(void) {
|
||||||
|
if (isatty(1)) {
|
||||||
|
write(1, ANSI_RESTORE, strlen(ANSI_RESTORE));
|
||||||
|
tcsetattr(1, TCSAFLUSH, &g_oldtermios);
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,7 +20,9 @@
|
||||||
#include "libc/calls/sigbits.h"
|
#include "libc/calls/sigbits.h"
|
||||||
#include "libc/calls/struct/sigaction.h"
|
#include "libc/calls/struct/sigaction.h"
|
||||||
#include "libc/calls/struct/siginfo.h"
|
#include "libc/calls/struct/siginfo.h"
|
||||||
|
#include "libc/calls/struct/termios.h"
|
||||||
#include "libc/calls/struct/utsname.h"
|
#include "libc/calls/struct/utsname.h"
|
||||||
|
#include "libc/calls/termios.h"
|
||||||
#include "libc/calls/ucontext.h"
|
#include "libc/calls/ucontext.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
|
@ -41,6 +43,7 @@
|
||||||
#include "libc/sysv/consts/fileno.h"
|
#include "libc/sysv/consts/fileno.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
|
#include "libc/sysv/consts/termios.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fileoverview Abnormal termination handling & GUI debugging.
|
* @fileoverview Abnormal termination handling & GUI debugging.
|
||||||
|
@ -262,6 +265,7 @@ relegated void __oncrash(int sig, struct siginfo *si, ucontext_t *ctx) {
|
||||||
: 0);
|
: 0);
|
||||||
}
|
}
|
||||||
if (gdbpid > 0 && (sig == SIGTRAP || sig == SIGQUIT)) return;
|
if (gdbpid > 0 && (sig == SIGTRAP || sig == SIGQUIT)) return;
|
||||||
|
__restore_tty();
|
||||||
ShowCrashReport(err, STDERR_FILENO, sig, si, ctx);
|
ShowCrashReport(err, STDERR_FILENO, sig, si, ctx);
|
||||||
exit(128 + sig);
|
exit(128 + sig);
|
||||||
unreachable;
|
unreachable;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "libc/bits/bits.h"
|
#include "libc/bits/bits.h"
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/sigbits.h"
|
#include "libc/calls/sigbits.h"
|
||||||
|
#include "libc/calls/termios.h"
|
||||||
#include "libc/calls/typedef/sigaction_f.h"
|
#include "libc/calls/typedef/sigaction_f.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/log/check.h"
|
#include "libc/log/check.h"
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
relegated void __start_fatal(const char *file, int line) {
|
relegated void __start_fatal(const char *file, int line) {
|
||||||
bool colorful;
|
bool colorful;
|
||||||
char s[16 + 16 + 16 + 16 + PATH_MAX + 16 + NAME_MAX + 16], *p = s;
|
char s[16 + 16 + 16 + 16 + PATH_MAX + 16 + NAME_MAX + 16], *p = s;
|
||||||
|
__restore_tty();
|
||||||
colorful = cancolor();
|
colorful = cancolor();
|
||||||
*p++ = '\r';
|
*p++ = '\r';
|
||||||
if (colorful) p = stpcpy(p, "\e[J\e[30;101m");
|
if (colorful) p = stpcpy(p, "\e[J\e[30;101m");
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
*/
|
*/
|
||||||
relegated void __start_fatal_ndebug(void) {
|
relegated void __start_fatal_ndebug(void) {
|
||||||
char s[16 + 16 + 16 + 16 + PATH_MAX + 16], *p = s;
|
char s[16 + 16 + 16 + 16 + PATH_MAX + 16], *p = s;
|
||||||
|
__restore_tty();
|
||||||
*p++ = '\r';
|
*p++ = '\r';
|
||||||
if (cancolor()) p = stpcpy(p, "\e[J");
|
if (cancolor()) p = stpcpy(p, "\e[J");
|
||||||
p = stpcpy(p, "error:");
|
p = stpcpy(p, "error:");
|
||||||
|
|
|
@ -45,10 +45,11 @@ static bool have_getrandom;
|
||||||
* This random number seed generator blends information from:
|
* This random number seed generator blends information from:
|
||||||
*
|
*
|
||||||
* - getrandom() on Linux
|
* - getrandom() on Linux
|
||||||
|
* - RtlGenRandom() on Windows
|
||||||
* - getentropy() on XNU and OpenBSD
|
* - getentropy() on XNU and OpenBSD
|
||||||
* - sysctl(KERN_ARND) on FreeBSD and NetBSD
|
* - sysctl(KERN_ARND) on FreeBSD and NetBSD
|
||||||
* - RDSEED on Broadwell+ and Xen+ unless GRND_NORDRND
|
* - RDSEED on Broadwell+ and Xen+ unless GRND_NORDRND
|
||||||
* - RDRAND on Ivybridge+ and Xen+ unless GRND_NORDRND|GRND_RANDOM
|
* - RDRAND on Ivybridge+ and Xen+ unless GRND_NORDRND
|
||||||
*
|
*
|
||||||
* The following flags may be specified:
|
* The following flags may be specified:
|
||||||
*
|
*
|
||||||
|
@ -75,7 +76,9 @@ ssize_t getrandom(void *p, size_t n, unsigned f) {
|
||||||
sigset_t neu, old;
|
sigset_t neu, old;
|
||||||
if (n > 256) n = 256;
|
if (n > 256) n = 256;
|
||||||
if (!IsTiny() &&
|
if (!IsTiny() &&
|
||||||
(f & ~(GRND_RANDOM | GRND_NONBLOCK | GRND_NORDRND | GRND_NOSYSTEM))) {
|
((f & ~(GRND_RANDOM | GRND_NONBLOCK | GRND_NORDRND | GRND_NOSYSTEM)) ||
|
||||||
|
(f & (GRND_NORDRND | GRND_NOSYSTEM)) ==
|
||||||
|
(GRND_NORDRND | GRND_NOSYSTEM))) {
|
||||||
return einval();
|
return einval();
|
||||||
}
|
}
|
||||||
if (!(f & GRND_NOSYSTEM)) {
|
if (!(f & GRND_NOSYSTEM)) {
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
/**
|
/**
|
||||||
* Fills memory with random bytes, e.g.
|
* Fills memory with random bytes, e.g.
|
||||||
*
|
*
|
||||||
* char buf[1024];
|
* char buf[1024];
|
||||||
* rngset(buf, sizeof(buf), rand64, -1);
|
* rngset(buf, sizeof(buf), rand64, -1);
|
||||||
*
|
*
|
||||||
* @param seed can be rand64() and is always called at least once
|
* @param seed can be rand64() and is always called at least once
|
||||||
* @param reseed is bytes between seed() calls and -1 disables it
|
* @param reseed is bytes between seed() calls and -1 disables it
|
||||||
|
|
|
@ -53,6 +53,7 @@ void *xunbinga(size_t, const char16_t *) attributeallocalign((1)) _XMAL _XRET;
|
||||||
void *xunbing(const char16_t *) _XMAL _XRET;
|
void *xunbing(const char16_t *) _XMAL _XRET;
|
||||||
char16_t *utf8toutf16(const char *, size_t, size_t *) nodiscard;
|
char16_t *utf8toutf16(const char *, size_t, size_t *) nodiscard;
|
||||||
char *utf16toutf8(const char16_t *, size_t, size_t *) nodiscard;
|
char *utf16toutf8(const char16_t *, size_t, size_t *) nodiscard;
|
||||||
|
char *xhomedir(void) nodiscard;
|
||||||
|
|
||||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||||
│ cosmopolitan § eXtended apis » files ─╬─│┼
|
│ cosmopolitan § eXtended apis » files ─╬─│┼
|
||||||
|
|
43
libc/x/xhomedir.c
Normal file
43
libc/x/xhomedir.c
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*-*- 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 2021 Justine Alexandra Roberts Tunney │
|
||||||
|
│ │
|
||||||
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||||
|
│ any purpose with or without fee is hereby granted, provided that the │
|
||||||
|
│ above copyright notice and this permission notice appear in all copies. │
|
||||||
|
│ │
|
||||||
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||||
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||||
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||||
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||||
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||||
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/x/x.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns home directory.
|
||||||
|
*/
|
||||||
|
char *xhomedir(void) {
|
||||||
|
int fd;
|
||||||
|
const char *a, *b;
|
||||||
|
if ((a = getenv("HOME"))) {
|
||||||
|
b = "";
|
||||||
|
} else if (IsWindows()) {
|
||||||
|
a = getenv("HOMEDRIVE");
|
||||||
|
b = getenv("HOMEPATH");
|
||||||
|
if (!a || !b) {
|
||||||
|
a = "C:";
|
||||||
|
b = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
a = ".";
|
||||||
|
b = "";
|
||||||
|
}
|
||||||
|
return xasprintf("%s%s", a, b);
|
||||||
|
}
|
261
third_party/linenoise/linenoise.c
vendored
261
third_party/linenoise/linenoise.c
vendored
|
@ -15,6 +15,7 @@
|
||||||
│ │
|
│ │
|
||||||
│ Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com> │
|
│ Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com> │
|
||||||
│ Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com> │
|
│ Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com> │
|
||||||
|
│ Copyright (c) 2018-2020, Justine Tunney <jtunney at gmail dot com> │
|
||||||
│ │
|
│ │
|
||||||
│ All rights reserved. │
|
│ All rights reserved. │
|
||||||
│ │
|
│ │
|
||||||
|
@ -43,67 +44,22 @@
|
||||||
│ │
|
│ │
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ │
|
│ │
|
||||||
│ Todo list: │
|
│ CHANGES │
|
||||||
│ - Filter bogus Ctrl+<char> combinations. │
|
|
||||||
│ - Win32 support │
|
|
||||||
│ │
|
│ │
|
||||||
│ Bloat: [say what?!] MUST DO: │
|
│ - Remove bell │
|
||||||
│ - History search like Ctrl+r in readline? │
|
│ - Windows support │
|
||||||
|
│ - Filters out unsupported control sequences │
|
||||||
|
│ - Filters out Thompson-Pike input sequences │
|
||||||
│ │
|
│ │
|
||||||
│ List of escape sequences used by this program, we do everything just │
|
│ TODO │
|
||||||
│ with three sequences. In order to be so cheap we may have some │
|
|
||||||
│ flickering effect with some slow terminal, but the lesser sequences │
|
|
||||||
│ the more compatible. │
|
|
||||||
│ │
|
│ │
|
||||||
│ EL (Erase Line) │
|
│ - Kill ring │
|
||||||
│ Sequence: ESC [ n K │
|
│ - History search │
|
||||||
│ Effect: if n is 0 or missing, clear from cursor to end of line │
|
│ - Thompson-Pike Encoding │
|
||||||
│ Effect: if n is 1, clear from beginning of line to cursor │
|
|
||||||
│ Effect: if n is 2, clear entire line │
|
|
||||||
│ │
|
|
||||||
│ CUF (CUrsor Forward) │
|
|
||||||
│ Sequence: ESC [ n C │
|
|
||||||
│ Effect: moves cursor forward n chars │
|
|
||||||
│ │
|
|
||||||
│ CUB (CUrsor Backward) │
|
|
||||||
│ Sequence: ESC [ n D │
|
|
||||||
│ Effect: moves cursor backward n chars │
|
|
||||||
│ │
|
|
||||||
│ The following is used to get the terminal width if getting │
|
|
||||||
│ the width with the TIOCGWINSZ ioctl fails │
|
|
||||||
│ │
|
|
||||||
│ DSR (Device Status Report) │
|
|
||||||
│ Sequence: ESC [ 6 n │
|
|
||||||
│ Effect: reports the current cusor position as ESC [ n ; m R │
|
|
||||||
│ where n is the row and m is the column │
|
|
||||||
│ │
|
|
||||||
│ When multi line mode is enabled, we also use an additional escape │
|
|
||||||
│ sequence. However multi line editing is disabled by default. │
|
|
||||||
│ │
|
|
||||||
│ CUU (Cursor Up) │
|
|
||||||
│ Sequence: ESC [ n A │
|
|
||||||
│ Effect: moves cursor up of n chars. │
|
|
||||||
│ │
|
|
||||||
│ CUD (Cursor Down) │
|
|
||||||
│ Sequence: ESC [ n B │
|
|
||||||
│ Effect: moves cursor down of n chars. │
|
|
||||||
│ │
|
|
||||||
│ When linenoiseClearScreen() is called, two additional escape sequences │
|
|
||||||
│ are used in order to clear the screen and position the cursor at home │
|
|
||||||
│ position. │
|
|
||||||
│ │
|
|
||||||
│ CUP (Cursor position) │
|
|
||||||
│ Sequence: ESC [ H │
|
|
||||||
│ Effect: moves the cursor to upper left corner │
|
|
||||||
│ │
|
|
||||||
│ ED (Erase display) │
|
|
||||||
│ Sequence: ESC [ 2 J │
|
|
||||||
│ Effect: clear the whole screen │
|
|
||||||
│ │
|
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
||||||
│ │
|
│ │
|
||||||
│ REFERENCE │
|
│ REFERENCE │
|
||||||
│ the big scary coding you 𝘮𝘶𝘴𝘵 use curses to abstract │
|
│ │
|
||||||
|
│ The big scary coding you 𝘮𝘶𝘴𝘵 use curses to abstract. │
|
||||||
│ │
|
│ │
|
||||||
│ \t TAB │
|
│ \t TAB │
|
||||||
│ \a BELL │
|
│ \a BELL │
|
||||||
|
@ -221,6 +177,7 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/termios.h"
|
#include "libc/calls/termios.h"
|
||||||
|
#include "libc/calls/ttydefaults.h"
|
||||||
#include "libc/calls/weirdtypes.h"
|
#include "libc/calls/weirdtypes.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
|
@ -267,28 +224,6 @@ struct linenoiseState {
|
||||||
int history_index; /* The history index we are currently editing. */
|
int history_index; /* The history index we are currently editing. */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum KEY_ACTION{
|
|
||||||
KEY_NULL = 0, /* NULL */
|
|
||||||
CTRL_A = 1, /* Ctrl+a */
|
|
||||||
CTRL_B = 2, /* Ctrl-b */
|
|
||||||
CTRL_C = 3, /* Ctrl-c */
|
|
||||||
CTRL_D = 4, /* Ctrl-d */
|
|
||||||
CTRL_E = 5, /* Ctrl-e */
|
|
||||||
CTRL_F = 6, /* Ctrl-f */
|
|
||||||
CTRL_H = 8, /* Ctrl-h */
|
|
||||||
TAB = 9, /* Tab */
|
|
||||||
CTRL_K = 11, /* Ctrl+k */
|
|
||||||
CTRL_L = 12, /* Ctrl+l */
|
|
||||||
ENTER = 13, /* Enter */
|
|
||||||
CTRL_N = 14, /* Ctrl-n */
|
|
||||||
CTRL_P = 16, /* Ctrl-p */
|
|
||||||
CTRL_T = 20, /* Ctrl-t */
|
|
||||||
CTRL_U = 21, /* Ctrl+u */
|
|
||||||
CTRL_W = 23, /* Ctrl+w */
|
|
||||||
ESC = 27, /* Escape */
|
|
||||||
BACKSPACE = 127 /* Backspace */
|
|
||||||
};
|
|
||||||
|
|
||||||
static void linenoiseAtExit(void);
|
static void linenoiseAtExit(void);
|
||||||
static void refreshLine(struct linenoiseState *);
|
static void refreshLine(struct linenoiseState *);
|
||||||
|
|
||||||
|
@ -362,7 +297,7 @@ static int enableRawMode(int fd) {
|
||||||
raw.c_oflag &= ~(OPOST);
|
raw.c_oflag &= ~(OPOST);
|
||||||
/* control modes - set 8 bit chars */
|
/* control modes - set 8 bit chars */
|
||||||
raw.c_cflag |= (CS8);
|
raw.c_cflag |= (CS8);
|
||||||
/* local modes - choing off, canonical off, no extended functions,
|
/* local modes - echoing off, canonical off, no extended functions,
|
||||||
* no signal chars (^Z,^C) */
|
* no signal chars (^Z,^C) */
|
||||||
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN);
|
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN);
|
||||||
/* control chars - set return condition: min number of bytes and timer.
|
/* control chars - set return condition: min number of bytes and timer.
|
||||||
|
@ -391,7 +326,7 @@ static int getCursorPosition(int ifd, int ofd) {
|
||||||
int cols, rows;
|
int cols, rows;
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
/* Report cursor location */
|
/* Report cursor location */
|
||||||
if (write(ofd, "\x1b[6n", 4) != 4) return -1;
|
if (write(ofd, "\e[6n", 4) != 4) return -1;
|
||||||
/* Read the response: ESC [ rows ; cols R */
|
/* Read the response: ESC [ rows ; cols R */
|
||||||
while (i < sizeof(buf)-1) {
|
while (i < sizeof(buf)-1) {
|
||||||
if (read(ifd,buf+i,1) != 1) break;
|
if (read(ifd,buf+i,1) != 1) break;
|
||||||
|
@ -400,7 +335,7 @@ static int getCursorPosition(int ifd, int ofd) {
|
||||||
}
|
}
|
||||||
buf[i] = '\0';
|
buf[i] = '\0';
|
||||||
/* Parse it. */
|
/* Parse it. */
|
||||||
if (buf[0] != ESC || buf[1] != '[') return -1;
|
if (buf[0] != '\e' || buf[1] != '[') return -1;
|
||||||
if (sscanf(buf+2,"%d;%d",&rows,&cols) != 2) return -1;
|
if (sscanf(buf+2,"%d;%d",&rows,&cols) != 2) return -1;
|
||||||
return cols;
|
return cols;
|
||||||
}
|
}
|
||||||
|
@ -416,13 +351,13 @@ static int getColumns(int ifd, int ofd) {
|
||||||
start = getCursorPosition(ifd,ofd);
|
start = getCursorPosition(ifd,ofd);
|
||||||
if (start == -1) goto failed;
|
if (start == -1) goto failed;
|
||||||
/* Go to right margin and get position. */
|
/* Go to right margin and get position. */
|
||||||
if (write(ofd,"\x1b[999C",6) != 6) goto failed;
|
if (write(ofd,"\e[999C",6) != 6) goto failed;
|
||||||
cols = getCursorPosition(ifd,ofd);
|
cols = getCursorPosition(ifd,ofd);
|
||||||
if (cols == -1) goto failed;
|
if (cols == -1) goto failed;
|
||||||
/* Restore position. */
|
/* Restore position. */
|
||||||
if (cols > start) {
|
if (cols > start) {
|
||||||
char seq[32];
|
char seq[32];
|
||||||
snprintf(seq,32,"\x1b[%dD",cols-start);
|
snprintf(seq,32,"\e[%dD",cols-start);
|
||||||
if (write(ofd,seq,strlen(seq)) == -1) {
|
if (write(ofd,seq,strlen(seq)) == -1) {
|
||||||
/* Can't recover... */
|
/* Can't recover... */
|
||||||
}
|
}
|
||||||
|
@ -437,7 +372,7 @@ failed:
|
||||||
|
|
||||||
/* Clear the screen. Used to handle ctrl+l */
|
/* Clear the screen. Used to handle ctrl+l */
|
||||||
void linenoiseClearScreen(void) {
|
void linenoiseClearScreen(void) {
|
||||||
if (write(STDOUT_FILENO,"\x1b[H\x1b[2J",7) <= 0) {
|
if (write(STDOUT_FILENO,"\e[H\e[2J",7) <= 0) {
|
||||||
/* nothing to do, just to avoid warning. */
|
/* nothing to do, just to avoid warning. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,7 +380,8 @@ void linenoiseClearScreen(void) {
|
||||||
/* Beep, used for completion when there is nothing to complete or when all
|
/* Beep, used for completion when there is nothing to complete or when all
|
||||||
* the choices were already shown. */
|
* the choices were already shown. */
|
||||||
static void linenoiseBeep(void) {
|
static void linenoiseBeep(void) {
|
||||||
fprintf(stderr, "\x7");
|
/* NOOOO */
|
||||||
|
/* fprintf(stderr, "\x7"); */
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,11 +430,11 @@ static int completeLine(struct linenoiseState *ls) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 9: /* tab */
|
case '\t':
|
||||||
i = (i+1) % (lc.len+1);
|
i = (i+1) % (lc.len+1);
|
||||||
if (i == lc.len) linenoiseBeep();
|
if (i == lc.len) linenoiseBeep();
|
||||||
break;
|
break;
|
||||||
case 27: /* escape */
|
case '\e':
|
||||||
/* Re-show original buffer */
|
/* Re-show original buffer */
|
||||||
if (i < lc.len) refreshLine(ls);
|
if (i < lc.len) refreshLine(ls);
|
||||||
stop = 1;
|
stop = 1;
|
||||||
|
@ -595,13 +531,13 @@ void refreshShowHints(struct abuf *ab, struct linenoiseState *l, int plen) {
|
||||||
if (hintlen > hintmaxlen) hintlen = hintmaxlen;
|
if (hintlen > hintmaxlen) hintlen = hintmaxlen;
|
||||||
if (bold == 1 && color == -1) color = 37;
|
if (bold == 1 && color == -1) color = 37;
|
||||||
if (color != -1 || bold != 0)
|
if (color != -1 || bold != 0)
|
||||||
snprintf(seq,64,"\033[%d;%d;49m",bold,color);
|
snprintf(seq,64,"\e[%d;%d;49m",bold,color);
|
||||||
else
|
else
|
||||||
seq[0] = '\0';
|
seq[0] = '\0';
|
||||||
abAppend(ab,seq,strlen(seq));
|
abAppend(ab,seq,strlen(seq));
|
||||||
abAppend(ab,hint,hintlen);
|
abAppend(ab,hint,hintlen);
|
||||||
if (color != -1 || bold != 0)
|
if (color != -1 || bold != 0)
|
||||||
abAppend(ab,"\033[0m",4);
|
abAppend(ab,"\e[0m",4);
|
||||||
/* Call the function to free the hint returned. */
|
/* Call the function to free the hint returned. */
|
||||||
if (freeHintsCallback) freeHintsCallback(hint);
|
if (freeHintsCallback) freeHintsCallback(hint);
|
||||||
}
|
}
|
||||||
|
@ -642,10 +578,10 @@ static void refreshSingleLine(struct linenoiseState *l) {
|
||||||
/* Show hits if any. */
|
/* Show hits if any. */
|
||||||
refreshShowHints(&ab,l,plen);
|
refreshShowHints(&ab,l,plen);
|
||||||
/* Erase to right */
|
/* Erase to right */
|
||||||
snprintf(seq,64,"\x1b[0K");
|
snprintf(seq,64,"\e[0K");
|
||||||
abAppend(&ab,seq,strlen(seq));
|
abAppend(&ab,seq,strlen(seq));
|
||||||
/* Move cursor to original position. */
|
/* Move cursor to original position. */
|
||||||
snprintf(seq,64,"\r\x1b[%dC", (int)(pos+plen));
|
snprintf(seq,64,"\r\e[%dC", (int)(pos+plen));
|
||||||
abAppend(&ab,seq,strlen(seq));
|
abAppend(&ab,seq,strlen(seq));
|
||||||
if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */
|
if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */
|
||||||
abFree(&ab);
|
abFree(&ab);
|
||||||
|
@ -672,18 +608,18 @@ static void refreshMultiLine(struct linenoiseState *l) {
|
||||||
abInit(&ab);
|
abInit(&ab);
|
||||||
if (old_rows-rpos > 0) {
|
if (old_rows-rpos > 0) {
|
||||||
lndebug("go down %d", old_rows-rpos);
|
lndebug("go down %d", old_rows-rpos);
|
||||||
snprintf(seq,64,"\x1b[%dB", old_rows-rpos);
|
snprintf(seq,64,"\e[%dB", old_rows-rpos);
|
||||||
abAppend(&ab,seq,strlen(seq));
|
abAppend(&ab,seq,strlen(seq));
|
||||||
}
|
}
|
||||||
/* Now for every row clear it, go up. */
|
/* Now for every row clear it, go up. */
|
||||||
for (j = 0; j < old_rows-1; j++) {
|
for (j = 0; j < old_rows-1; j++) {
|
||||||
lndebug("clear+up");
|
lndebug("clear+up");
|
||||||
snprintf(seq,64,"\r\x1b[0K\x1b[1A");
|
snprintf(seq,64,"\r\e[0K\e[1A");
|
||||||
abAppend(&ab,seq,strlen(seq));
|
abAppend(&ab,seq,strlen(seq));
|
||||||
}
|
}
|
||||||
/* Clean the top line. */
|
/* Clean the top line. */
|
||||||
lndebug("clear");
|
lndebug("clear");
|
||||||
snprintf(seq,64,"\r\x1b[0K");
|
snprintf(seq,64,"\r\e[0K");
|
||||||
abAppend(&ab,seq,strlen(seq));
|
abAppend(&ab,seq,strlen(seq));
|
||||||
/* Write the prompt and the current buffer content */
|
/* Write the prompt and the current buffer content */
|
||||||
abAppend(&ab,l->prompt,strlen(l->prompt));
|
abAppend(&ab,l->prompt,strlen(l->prompt));
|
||||||
|
@ -714,14 +650,14 @@ static void refreshMultiLine(struct linenoiseState *l) {
|
||||||
/* Go up till we reach the expected positon. */
|
/* Go up till we reach the expected positon. */
|
||||||
if (rows-rpos2 > 0) {
|
if (rows-rpos2 > 0) {
|
||||||
lndebug("go-up %d", rows-rpos2);
|
lndebug("go-up %d", rows-rpos2);
|
||||||
snprintf(seq,64,"\x1b[%dA", rows-rpos2);
|
snprintf(seq,64,"\e[%dA", rows-rpos2);
|
||||||
abAppend(&ab,seq,strlen(seq));
|
abAppend(&ab,seq,strlen(seq));
|
||||||
}
|
}
|
||||||
/* Set column. */
|
/* Set column. */
|
||||||
col = (plen+(int)l->pos) % (int)l->cols;
|
col = (plen+(int)l->pos) % (int)l->cols;
|
||||||
lndebug("set col %d", 1+col);
|
lndebug("set col %d", 1+col);
|
||||||
if (col)
|
if (col)
|
||||||
snprintf(seq,64,"\r\x1b[%dC", col);
|
snprintf(seq,64,"\r\e[%dC", col);
|
||||||
else
|
else
|
||||||
snprintf(seq,64,"\r");
|
snprintf(seq,64,"\r");
|
||||||
abAppend(&ab,seq,strlen(seq));
|
abAppend(&ab,seq,strlen(seq));
|
||||||
|
@ -778,6 +714,28 @@ void linenoiseEditMoveLeft(struct linenoiseState *l) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Move cursor on the left. */
|
||||||
|
void linenoiseEditMoveLeftWord(struct linenoiseState *l) {
|
||||||
|
if (l->pos > 0) {
|
||||||
|
while (l->pos > 0 && l->buf[l->pos-1] == ' ')
|
||||||
|
l->pos--;
|
||||||
|
while (l->pos > 0 && l->buf[l->pos-1] != ' ')
|
||||||
|
l->pos--;
|
||||||
|
refreshLine(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move cursor on the right. */
|
||||||
|
void linenoiseEditMoveRightWord(struct linenoiseState *l) {
|
||||||
|
if (l->pos != l->len) {
|
||||||
|
while (l->pos < l->len && l->buf[l->pos] == ' ')
|
||||||
|
l->pos++;
|
||||||
|
while (l->pos < l->len && l->buf[l->pos] != ' ')
|
||||||
|
l->pos++;
|
||||||
|
refreshLine(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Move cursor on the right. */
|
/* Move cursor on the right. */
|
||||||
void linenoiseEditMoveRight(struct linenoiseState *l) {
|
void linenoiseEditMoveRight(struct linenoiseState *l) {
|
||||||
if (l->pos != l->len) {
|
if (l->pos != l->len) {
|
||||||
|
@ -896,15 +854,17 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen,
|
||||||
linenoiseHistoryAdd("");
|
linenoiseHistoryAdd("");
|
||||||
if (write(l.ofd,prompt,l.plen) == -1) return -1;
|
if (write(l.ofd,prompt,l.plen) == -1) return -1;
|
||||||
while(1) {
|
while(1) {
|
||||||
char c;
|
int i;
|
||||||
|
int c;
|
||||||
int nread;
|
int nread;
|
||||||
char seq[3];
|
char seq[32];
|
||||||
nread = read(l.ifd,&c,1);
|
nread = readansi(l.ifd,seq,sizeof(seq));
|
||||||
if (nread <= 0) return l.len;
|
if (nread <= 0) return l.len;
|
||||||
|
c = seq[0];
|
||||||
/* Only autocomplete when the callback is set. It returns < 0 when
|
/* Only autocomplete when the callback is set. It returns < 0 when
|
||||||
* there was an error reading from fd. Otherwise it will return the
|
* there was an error reading from fd. Otherwise it will return the
|
||||||
* character that should be handled next. */
|
* character that should be handled next. */
|
||||||
if (c == 9 && completionCallback != NULL) {
|
if (c == '\t' && completionCallback) {
|
||||||
c = completeLine(&l);
|
c = completeLine(&l);
|
||||||
/* Return on errors */
|
/* Return on errors */
|
||||||
if (c < 0) return l.len;
|
if (c < 0) return l.len;
|
||||||
|
@ -912,7 +872,7 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen,
|
||||||
if (c == 0) continue;
|
if (c == 0) continue;
|
||||||
}
|
}
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case ENTER: /* enter */
|
case '\r': /* enter */
|
||||||
history_len--;
|
history_len--;
|
||||||
free(history[history_len]);
|
free(history[history_len]);
|
||||||
if (mlmode) linenoiseEditMoveEnd(&l);
|
if (mlmode) linenoiseEditMoveEnd(&l);
|
||||||
|
@ -925,15 +885,15 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen,
|
||||||
hintsCallback = hc;
|
hintsCallback = hc;
|
||||||
}
|
}
|
||||||
return (int)l.len;
|
return (int)l.len;
|
||||||
case CTRL_C: /* ctrl-c */
|
case CTRL('C'):
|
||||||
errno = EAGAIN;
|
errno = EAGAIN;
|
||||||
return -1;
|
return -1;
|
||||||
case BACKSPACE: /* backspace */
|
case CTRL('?'): /* backspace a.k.a. 0177 a.k.a. 127 */
|
||||||
case 8: /* ctrl-h */
|
case CTRL('H'):
|
||||||
linenoiseEditBackspace(&l);
|
linenoiseEditBackspace(&l);
|
||||||
break;
|
break;
|
||||||
case CTRL_D: /* ctrl-d, remove char at right of cursor, or if the
|
case CTRL('D'): /* remove char at right of cursor, or if the
|
||||||
line is empty, act as end-of-file. */
|
line is empty, act as end-of-file. */
|
||||||
if (l.len > 0) {
|
if (l.len > 0) {
|
||||||
linenoiseEditDelete(&l);
|
linenoiseEditDelete(&l);
|
||||||
} else {
|
} else {
|
||||||
|
@ -942,7 +902,7 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CTRL_T: /* ctrl-t, swaps current character with previous. */
|
case CTRL('T'): /* swaps current character with previous. */
|
||||||
if (l.pos > 0 && l.pos < l.len) {
|
if (l.pos > 0 && l.pos < l.len) {
|
||||||
int aux = buf[l.pos-1];
|
int aux = buf[l.pos-1];
|
||||||
buf[l.pos-1] = buf[l.pos];
|
buf[l.pos-1] = buf[l.pos];
|
||||||
|
@ -951,95 +911,110 @@ static int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, size_t buflen,
|
||||||
refreshLine(&l);
|
refreshLine(&l);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CTRL_B: /* ctrl-b */
|
case CTRL('B'):
|
||||||
linenoiseEditMoveLeft(&l);
|
linenoiseEditMoveLeft(&l);
|
||||||
break;
|
break;
|
||||||
case CTRL_F: /* ctrl-f */
|
case CTRL('F'):
|
||||||
linenoiseEditMoveRight(&l);
|
linenoiseEditMoveRight(&l);
|
||||||
break;
|
break;
|
||||||
case CTRL_P: /* ctrl-p */
|
case CTRL('P'):
|
||||||
linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
|
linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
|
||||||
break;
|
break;
|
||||||
case CTRL_N: /* ctrl-n */
|
case CTRL('N'):
|
||||||
linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
|
linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
|
||||||
break;
|
break;
|
||||||
case ESC: /* escape sequence */
|
case '\e': /* escape sequence */
|
||||||
/* Read the next two bytes representing the escape sequence.
|
/* Read the next two bytes representing the escape sequence.
|
||||||
* Use two calls to handle slow terminals returning the two
|
* Use two calls to handle slow terminals returning the two
|
||||||
* chars at different times. */
|
* chars at different times. */
|
||||||
if (read(l.ifd,seq,1) == -1) break;
|
if (nread < 2) break;
|
||||||
if (read(l.ifd,seq+1,1) == -1) break;
|
if (seq[1] == '[') {
|
||||||
/* ESC [ sequences. */
|
if (nread < 3) break;
|
||||||
if (seq[0] == '[') {
|
if (seq[2] >= '0' && seq[2] <= '9') {
|
||||||
if (seq[1] >= '0' && seq[1] <= '9') {
|
if (nread < 4) break;
|
||||||
/* Extended escape, read additional byte. */
|
if (seq[3] == '~') {
|
||||||
if (read(l.ifd,seq+2,1) == -1) break;
|
switch(seq[2]) {
|
||||||
if (seq[2] == '~') {
|
case '1': /* "\e[1~" is home */
|
||||||
switch(seq[1]) {
|
linenoiseEditMoveHome(&l);
|
||||||
case '3': /* Delete key. */
|
break;
|
||||||
|
case '3': /* "\e[3~" is delete */
|
||||||
linenoiseEditDelete(&l);
|
linenoiseEditDelete(&l);
|
||||||
break;
|
break;
|
||||||
|
case '4': /* "\e[4~" is end */
|
||||||
|
linenoiseEditMoveEnd(&l);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch(seq[1]) {
|
switch(seq[2]) {
|
||||||
case 'A': /* Up */
|
case 'A': /* "\e[A" is up */
|
||||||
linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
|
linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_PREV);
|
||||||
break;
|
break;
|
||||||
case 'B': /* Down */
|
case 'B': /* "\e[B" is down */
|
||||||
linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
|
linenoiseEditHistoryNext(&l, LINENOISE_HISTORY_NEXT);
|
||||||
break;
|
break;
|
||||||
case 'C': /* Right */
|
case 'C': /* "\e[C" is right */
|
||||||
linenoiseEditMoveRight(&l);
|
linenoiseEditMoveRight(&l);
|
||||||
break;
|
break;
|
||||||
case 'D': /* Left */
|
case 'D': /* "\e[D" is left */
|
||||||
linenoiseEditMoveLeft(&l);
|
linenoiseEditMoveLeft(&l);
|
||||||
break;
|
break;
|
||||||
case 'H': /* Home */
|
case 'H': /* "\e[H" is home */
|
||||||
linenoiseEditMoveHome(&l);
|
linenoiseEditMoveHome(&l);
|
||||||
break;
|
break;
|
||||||
case 'F': /* End*/
|
case 'F': /* "\e[F" is end */
|
||||||
linenoiseEditMoveEnd(&l);
|
linenoiseEditMoveEnd(&l);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* ESC O sequences. */
|
else if (seq[1] == 'O') {
|
||||||
else if (seq[0] == 'O') {
|
if (nread < 3) break;
|
||||||
switch(seq[1]) {
|
switch(seq[2]) {
|
||||||
case 'H': /* Home */
|
case 'H': /* "\eOH" is home */
|
||||||
linenoiseEditMoveHome(&l);
|
linenoiseEditMoveHome(&l);
|
||||||
break;
|
break;
|
||||||
case 'F': /* End*/
|
case 'F': /* "\eOF" is end */
|
||||||
linenoiseEditMoveEnd(&l);
|
linenoiseEditMoveEnd(&l);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (seq[1] == 'b') { /* "\eb" is alt-b */
|
||||||
|
linenoiseEditMoveLeftWord(&l);
|
||||||
|
} else if (seq[1] == 'f') { /* "\ef" is alt-f */
|
||||||
|
linenoiseEditMoveRightWord(&l);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (linenoiseEditInsert(&l,c)) return -1;
|
if (32 <= seq[0] && seq[0] < 127) {
|
||||||
|
if (linenoiseEditInsert(&l,seq[0])==-1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CTRL_U: /* Ctrl+u, delete the whole line. */
|
case CTRL('U'): /* delete the whole line */
|
||||||
|
/* TODO(jart): delete backwards */
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
l.pos = l.len = 0;
|
l.pos = l.len = 0;
|
||||||
refreshLine(&l);
|
refreshLine(&l);
|
||||||
break;
|
break;
|
||||||
case CTRL_K: /* Ctrl+k, delete from current to end of line. */
|
case CTRL('K'): /* delete from current to end of line */
|
||||||
|
/* TODO(jart): add to kill ring */
|
||||||
buf[l.pos] = '\0';
|
buf[l.pos] = '\0';
|
||||||
l.len = l.pos;
|
l.len = l.pos;
|
||||||
refreshLine(&l);
|
refreshLine(&l);
|
||||||
break;
|
break;
|
||||||
case CTRL_A: /* Ctrl+a, go to the start of the line */
|
case CTRL('A'): /* go to the start of the line */
|
||||||
linenoiseEditMoveHome(&l);
|
linenoiseEditMoveHome(&l);
|
||||||
break;
|
break;
|
||||||
case CTRL_E: /* ctrl+e, go to the end of the line */
|
case CTRL('E'): /* go to the end of the line */
|
||||||
linenoiseEditMoveEnd(&l);
|
linenoiseEditMoveEnd(&l);
|
||||||
break;
|
break;
|
||||||
case CTRL_L: /* ctrl+l, clear screen */
|
case CTRL('L'): /* clear screen */
|
||||||
linenoiseClearScreen();
|
linenoiseClearScreen();
|
||||||
refreshLine(&l);
|
refreshLine(&l);
|
||||||
break;
|
break;
|
||||||
case CTRL_W: /* ctrl+w, delete previous word */
|
case CTRL('W'): /* delete previous word */
|
||||||
linenoiseEditDeletePrevWord(&l);
|
linenoiseEditDeletePrevWord(&l);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1083,7 +1058,7 @@ static int linenoiseRaw(char *buf, size_t buflen, const char *prompt) {
|
||||||
if (enableRawMode(STDIN_FILENO) == -1) return -1;
|
if (enableRawMode(STDIN_FILENO) == -1) return -1;
|
||||||
count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt);
|
count = linenoiseEdit(STDIN_FILENO, STDOUT_FILENO, buf, buflen, prompt);
|
||||||
linenoiseDisableRawMode(STDIN_FILENO);
|
linenoiseDisableRawMode(STDIN_FILENO);
|
||||||
printf("\n");
|
if (count != -1) printf("\n");
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1154,8 +1129,6 @@ void linenoiseFree(void *ptr) {
|
||||||
free(ptr);
|
free(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================ History ================================= */
|
|
||||||
|
|
||||||
/* Free the history, but does not reset it. Only used when we have to
|
/* Free the history, but does not reset it. Only used when we have to
|
||||||
* exit() to avoid memory leaks are reported by valgrind & co. */
|
* exit() to avoid memory leaks are reported by valgrind & co. */
|
||||||
static void freeHistory(void) {
|
static void freeHistory(void) {
|
||||||
|
|
13
third_party/python/Modules/getbuildinfo.c
vendored
13
third_party/python/Modules/getbuildinfo.c
vendored
|
@ -38,18 +38,7 @@
|
||||||
const char *
|
const char *
|
||||||
Py_GetBuildInfo(void)
|
Py_GetBuildInfo(void)
|
||||||
{
|
{
|
||||||
static char buildinfo[50 + sizeof(GITVERSION) +
|
return "cosmopolitan";
|
||||||
((sizeof(GITTAG) > sizeof(GITBRANCH)) ?
|
|
||||||
sizeof(GITTAG) : sizeof(GITBRANCH))];
|
|
||||||
const char *revision = _Py_gitversion();
|
|
||||||
const char *sep = *revision ? ":" : "";
|
|
||||||
const char *gitid = _Py_gitidentifier();
|
|
||||||
if (!(*gitid))
|
|
||||||
gitid = "default";
|
|
||||||
PyOS_snprintf(buildinfo, sizeof(buildinfo),
|
|
||||||
"%s%s%s, %.20s, %.9s", gitid, sep, revision,
|
|
||||||
DATE, TIME);
|
|
||||||
return buildinfo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
|
1
third_party/python/Modules/getpath.c
vendored
1
third_party/python/Modules/getpath.c
vendored
|
@ -492,7 +492,6 @@ calculate_path(void)
|
||||||
|
|
||||||
if(IsWindows())
|
if(IsWindows())
|
||||||
{
|
{
|
||||||
fprintf(stderr, "python APE on Windows\n");
|
|
||||||
delimiter[0] = L';';
|
delimiter[0] = L';';
|
||||||
separator[0] = L'\\';
|
separator[0] = L'\\';
|
||||||
}
|
}
|
||||||
|
|
80
third_party/python/Programs/python.c
vendored
80
third_party/python/Programs/python.c
vendored
|
@ -7,17 +7,24 @@
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/log/check.h"
|
#include "libc/log/check.h"
|
||||||
|
#include "libc/log/log.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/fileno.h"
|
#include "libc/sysv/consts/fileno.h"
|
||||||
#include "libc/sysv/consts/sig.h"
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "libc/unicode/locale.h"
|
#include "libc/unicode/locale.h"
|
||||||
#include "third_party/linenoise/linenoise.h"
|
#include "third_party/linenoise/linenoise.h"
|
||||||
|
#include "third_party/python/Include/ceval.h"
|
||||||
|
#include "third_party/python/Include/dictobject.h"
|
||||||
#include "third_party/python/Include/fileutils.h"
|
#include "third_party/python/Include/fileutils.h"
|
||||||
|
#include "third_party/python/Include/import.h"
|
||||||
#include "third_party/python/Include/pylifecycle.h"
|
#include "third_party/python/Include/pylifecycle.h"
|
||||||
#include "third_party/python/Include/pymem.h"
|
#include "third_party/python/Include/pymem.h"
|
||||||
#include "third_party/python/Include/pyport.h"
|
#include "third_party/python/Include/pyport.h"
|
||||||
#include "third_party/python/Include/pythonrun.h"
|
#include "third_party/python/Include/pythonrun.h"
|
||||||
|
#include "third_party/python/Include/unicodeobject.h"
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
static jmp_buf jbuf;
|
static jmp_buf jbuf;
|
||||||
|
@ -28,6 +35,77 @@ OnKeyboardInterrupt(int sig)
|
||||||
longjmp(jbuf, 1);
|
longjmp(jbuf, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
GetMember(const char *s, Py_ssize_t n, PyObject *o)
|
||||||
|
{
|
||||||
|
const char *t;
|
||||||
|
PyObject *k, *v;
|
||||||
|
Py_ssize_t i, m;
|
||||||
|
if (!o) return 0;
|
||||||
|
for (i = 0; PyDict_Next(o, &i, &k, &v);) {
|
||||||
|
if (v != Py_None && PyUnicode_Check(k)) {
|
||||||
|
t = PyUnicode_AsUTF8AndSize(k, &m);
|
||||||
|
printf("\r%`'.*s vs. %`'.*s\n", n, s, m, t);
|
||||||
|
if (n == m && !memcmp(s, t, n)) {
|
||||||
|
Py_INCREF(v);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
GetVar(const char *s, Py_ssize_t n)
|
||||||
|
{
|
||||||
|
PyObject *o;
|
||||||
|
/*
|
||||||
|
* TODO: Why doesn't PyEval_GetLocals() work?
|
||||||
|
*/
|
||||||
|
if ((o = GetMember(s, n, PyEval_GetLocals()))) return o;
|
||||||
|
if ((o = GetMember(s, n, PyEval_GetGlobals()))) return o;
|
||||||
|
if ((o = GetMember(s, n, PyEval_GetBuiltins()))) return o;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
TerminalComplete(const char *s, linenoiseCompletions *c, PyObject *o)
|
||||||
|
{
|
||||||
|
const char *t;
|
||||||
|
PyObject *k, *v;
|
||||||
|
Py_ssize_t i, n, m;
|
||||||
|
if (!o) return;
|
||||||
|
for (n = strlen(s), i = 0; PyDict_Next(o, &i, &k, &v);) {
|
||||||
|
if (v != Py_None && PyUnicode_Check(k)) {
|
||||||
|
t = PyUnicode_AsUTF8AndSize(k, &m);
|
||||||
|
if (m > n && !memcmp(t, s, n)) {
|
||||||
|
c->cvec = realloc(c->cvec, ++c->len * sizeof(*c->cvec));
|
||||||
|
c->cvec[c->len - 1] = strdup(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
TerminalCompletion(const char *s, linenoiseCompletions *c)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
PyObject *o, *q;
|
||||||
|
if ((p = strchr(s, '.'))) {
|
||||||
|
if (!(o = GetVar(s, p - s))) return;
|
||||||
|
for (s = p + 1; (p = strchr(s, '.')); o = q) {
|
||||||
|
if ((q = GetMember(s, p - s, o))) return;
|
||||||
|
Py_DECREF(o);
|
||||||
|
}
|
||||||
|
TerminalComplete(s, c, o);
|
||||||
|
Py_DECREF(o);
|
||||||
|
} else {
|
||||||
|
TerminalComplete(s, c, PyEval_GetLocals());
|
||||||
|
TerminalComplete(s, c, PyEval_GetGlobals());
|
||||||
|
TerminalComplete(s, c, PyEval_GetBuiltins());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
TerminalReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
|
TerminalReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
|
||||||
{
|
{
|
||||||
|
@ -66,6 +144,8 @@ main(int argc, char **argv)
|
||||||
int i, res;
|
int i, res;
|
||||||
char *oldloc;
|
char *oldloc;
|
||||||
|
|
||||||
|
showcrashreports();
|
||||||
|
linenoiseSetCompletionCallback(TerminalCompletion);
|
||||||
PyOS_ReadlineFunctionPointer = TerminalReadline;
|
PyOS_ReadlineFunctionPointer = TerminalReadline;
|
||||||
|
|
||||||
/* Force malloc() allocator to bootstrap Python */
|
/* Force malloc() allocator to bootstrap Python */
|
||||||
|
|
1
third_party/python/Python/pylifecycle.c
vendored
1
third_party/python/Python/pylifecycle.c
vendored
|
@ -14,6 +14,7 @@
|
||||||
#include "libc/log/log.h"
|
#include "libc/log/log.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/sysv/consts/sig.h"
|
||||||
#include "libc/unicode/locale.h"
|
#include "libc/unicode/locale.h"
|
||||||
#include "third_party/python/Include/Python-ast.h"
|
#include "third_party/python/Include/Python-ast.h"
|
||||||
#include "third_party/python/Include/abstract.h"
|
#include "third_party/python/Include/abstract.h"
|
||||||
|
|
|
@ -16,15 +16,11 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
|
||||||
#include "libc/calls/struct/stat.h"
|
#include "libc/calls/struct/stat.h"
|
||||||
#include "libc/dce.h"
|
|
||||||
#include "libc/fmt/fmt.h"
|
|
||||||
#include "libc/log/check.h"
|
#include "libc/log/check.h"
|
||||||
#include "libc/mem/mem.h"
|
#include "libc/runtime/gc.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
|
||||||
#include "libc/stdio/stdio.h"
|
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
|
#include "libc/x/x.h"
|
||||||
#include "tool/build/lib/psk.h"
|
#include "tool/build/lib/psk.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,23 +28,9 @@
|
||||||
*/
|
*/
|
||||||
void *GetRunitPsk(void) {
|
void *GetRunitPsk(void) {
|
||||||
int fd;
|
int fd;
|
||||||
|
char *r, *p;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const char *a, *b;
|
p = gc(xasprintf("%s/.runit.psk", gc(xhomedir())));
|
||||||
char *r, p[PATH_MAX + 1];
|
|
||||||
if ((a = getenv("HOME"))) {
|
|
||||||
b = "";
|
|
||||||
} else if (IsWindows()) {
|
|
||||||
a = getenv("HOMEDRIVE");
|
|
||||||
b = getenv("HOMEPATH");
|
|
||||||
if (!a || !b) {
|
|
||||||
a = "C:";
|
|
||||||
b = "";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, "need $HOME\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
snprintf(p, sizeof(p), "%s%s/.runit.psk", a, b);
|
|
||||||
if (stat(p, &st) == -1 || st.st_size != 32) {
|
if (stat(p, &st) == -1 || st.st_size != 32) {
|
||||||
fprintf(stderr, "need o//examples/getrandom.com -bn32 >~/.runit.psk\n");
|
fprintf(stderr, "need o//examples/getrandom.com -bn32 >~/.runit.psk\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -1216,6 +1216,27 @@ static optimizesize void ReadKeyboard(void) {
|
||||||
case 'S': /* \eOS is F4 */
|
case 'S': /* \eOS is F4 */
|
||||||
pf4_ = !pf4_;
|
pf4_ = !pf4_;
|
||||||
break;
|
break;
|
||||||
|
case 'T': /* \eOT is F5 */
|
||||||
|
pf5_ = !pf5_;
|
||||||
|
break;
|
||||||
|
case 'U': /* \eOU is F6 */
|
||||||
|
pf6_ = !pf6_;
|
||||||
|
break;
|
||||||
|
case 'V': /* \eOV is F7 */
|
||||||
|
pf7_ = !pf7_;
|
||||||
|
break;
|
||||||
|
case 'W': /* \eOW is F8 */
|
||||||
|
pf8_ = !pf8_;
|
||||||
|
break;
|
||||||
|
case 'Y': /* \eOY is F10 */
|
||||||
|
pf10_ = !pf10_;
|
||||||
|
break;
|
||||||
|
case 'Z': /* \eOZ is F11 */
|
||||||
|
pf11_ = !pf11_;
|
||||||
|
break;
|
||||||
|
case '[': /* \eO[ is F12 */
|
||||||
|
pf12_ = !pf12_;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue