Remove some dead code

This commit is contained in:
Justine Tunney 2023-07-03 02:47:05 -07:00
parent 168d1c157e
commit 73c0faa1b5
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
66 changed files with 324 additions and 7705 deletions

View file

@ -3,8 +3,7 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern bool __assert_disable;
void __assert_fail(const char *, const char *, int) _Hide relegated;
void __assert_fail(const char *, const char *, int) relegated;
#ifdef NDEBUG
#define assert(x) ((void)0)
@ -16,6 +15,8 @@ void __assert_fail(const char *, const char *, int) _Hide relegated;
#define static_assert _Static_assert
#endif
#ifdef COSMO
extern bool __assert_disable;
#ifndef NDEBUG
#define _unassert(x) __assert_macro(x, #x)
#define _npassert(x) __assert_macro(x, #x)
@ -42,7 +43,8 @@ void __assert_fail(const char *, const char *, int) _Hide relegated;
} \
(void)0; \
})
#endif
#endif /* NDEBUG */
#endif /* COSMO */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -1,7 +1,7 @@
/*-*- 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 2022 Justine Alexandra Roberts Tunney
Copyright 2023 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
@ -16,18 +16,19 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/elf/struct/ehdr.h"
#include "libc/fmt/itoa.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/auxv.h"
noasan int main(int argc, char *argv[]) {
int i = 0;
Elf64_Ehdr *ehdr;
ehdr = (Elf64_Ehdr *)getauxval(AT_SYSINFO_EHDR);
if (isatty(1)) exit(1);
for (;;) {
write(1, ((char *)ehdr) + i++, 1);
/**
* Handles assert() failure.
*/
void __assert_fail(const char *expr, const char *file, int line) {
char ibuf[12];
if (!__assert_disable) {
FormatInt32(ibuf, line);
tinyprint(2, file, ":", ibuf, ": assert(", expr, ") failed\n", NULL);
abort();
}
return 0;
}

View file

@ -62,7 +62,7 @@ COSMOPOLITAN_C_START_
typedef int sig_atomic_t;
bool32 isatty(int) nosideeffect;
bool32 isatty(int);
char *get_current_dir_name(void) dontdiscard;
char *getcwd(char *, size_t);
char *realpath(const char *, char *);

View file

@ -24,11 +24,8 @@
/**
* Writes error messages to standard error.
*/
void perror(const char *message) {
int err;
const char *estr;
estr = _strerdoc(errno);
if (!message) message = "";
if (!estr) estr = "Unknown error";
tinyprint(2, message, *message ? ": " : "", estr, "\n", NULL);
void perror(const char *thing) {
const char *reason;
if (!(reason = _strerdoc(errno))) reason = "Unknown error";
tinyprint(2, thing ? thing : "", thing ? ": " : "", reason, "\n", NULL);
}

View file

@ -17,7 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
// stub version of abort() for low-dependency apps
// stub version of abort() to keep the build a dag
__attribute__((__noreturn__, __weak__)) void abort(void) {
__builtin_trap();
}

View file

@ -1,7 +1,7 @@
/*-*- 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
Copyright 2023 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
@ -16,19 +16,9 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/conv.h"
#include "libc/math.h"
#include "libc/stdio/stdio.h"
int main(int argc, char *argv[]) {
int i, x, y;
for (i = 1; i < argc; ++i) {
x = atoi(argv[i]);
y = round(
(1.923 * cbrt(x * log(2)) * cbrt(log(x * log(2)) * log(x * log(2))) -
4.69) /
log(2));
printf("%4d %4d\n", x, y);
}
return 0;
// stub version of assert() to keep the build a dag
__attribute__((__weak__)) void __assert_fail(const char *expr, const char *file,
int line) {
__builtin_trap();
}

View file

@ -1,33 +0,0 @@
/*-*- 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
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/assert.h"
#include "libc/atomic.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/kprintf.h"
#include "libc/runtime/runtime.h"
privileged void __assert_fail(const char *expr, const char *file, int line) {
static atomic_bool once;
if (!__assert_disable) {
if (!atomic_exchange(&once, true)) {
kprintf("%s:%d: assert(%s) failed (tid %P) %m\n", file, line, expr);
}
__builtin_trap();
}
}

View file

@ -1,4 +1,4 @@
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_ALLOCA_H_
#define COSMOPOLITAN_LIBC_ISYSTEM_ALLOCA_H_
#ifndef _ALLOCA_H
#define _ALLOCA_H
#include "libc/mem/alloca.h"
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_ALLOCA_H_ */
#endif /* _ALLOCA_H */

View file

@ -1,4 +1,4 @@
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_AR_H_
#define COSMOPOLITAN_LIBC_ISYSTEM_AR_H_
#ifndef _AR_H
#define _AR_H
#include "libc/ar.h"
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_AR_H_ */
#endif /* _AR_H */

View file

@ -1,5 +1,5 @@
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_COSMO_H_
#define COSMOPOLITAN_LIBC_ISYSTEM_COSMO_H_
#ifndef _COSMO_H
#define _COSMO_H
#ifdef COSMO
#define COSMO_ALREADY_DEFINED
@ -65,4 +65,4 @@
#undef COSMO
#endif
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_COSMO_H_ */
#endif /* _COSMO_H */

View file

@ -1,8 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_MEM_ALLOCA_H_
#define COSMOPOLITAN_LIBC_MEM_ALLOCA_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define alloca(size) __builtin_alloca(size)
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_MEM_ALLOCA_H_ */

View file

@ -153,7 +153,7 @@ textstartup void cosmo(long *sp, struct Syslib *m1) {
__envp = envp;
__auxv = auxv;
environ = envp;
if (argc) program_invocation_name = argv[0];
program_invocation_name = argv[0];
// initialize program
_init();

View file

@ -60,8 +60,8 @@
? __ckd_##op##ll((__ckd_dword *)(res), (x), (y)) \
: __ckd_trap()))
__funline wontreturn int __ckd_trap(void) {
*(volatile int *)0 = 0;
__funline int __ckd_trap(void) {
return *(volatile int *)0 = 0;
}
/*

View file

@ -240,9 +240,10 @@ static int __fmt_ntoa_format(int out(const char *, void *, size_t), void *arg,
return 0;
}
static int ntoa2(int out(const char *, void *, size_t), void *arg,
uint128_t value, bool neg, unsigned log2base, unsigned prec,
unsigned width, unsigned flags, const char *alphabet) {
static int __fmt_ntoa2(int out(const char *, void *, size_t), void *arg,
uint128_t value, bool neg, unsigned log2base,
unsigned prec, unsigned width, unsigned flags,
const char *alphabet) {
uint128_t remainder;
unsigned len, count, digit;
char buf[BUFFER_SIZE];
@ -314,7 +315,7 @@ static int __fmt_ntoa(int out(const char *, void *, size_t), void *arg,
}
}
return ntoa2(out, arg, value, neg, log2base, prec, width, flags, lang);
return __fmt_ntoa2(out, arg, value, neg, log2base, prec, width, flags, lang);
}
/**

View file

@ -41,56 +41,27 @@ getopt (BSD-3)\\n\
Copyright 1987, 1993, 1994 The Regents of the University of California\"");
asm(".include \"libc/disclaimer.inc\"");
#define BADCH (int)'?'
#define BADARG (int)':'
#define BADCH '?'
#define BADARG ':'
/**
* If error message should be printed.
* @see getopt()
*/
int opterr;
int opterr; // If error message should be printed.
int optind; // Index into parent argv vector.
int optopt; // Character checked for validity.
int optreset; // Reset getopt.
char *optarg; // Argument associated with option.
/**
* Index into parent argv vector.
* @see getopt()
*/
int optind;
static struct {
char once;
char emsg[1];
char *place;
} optglob;
/**
* Character checked for validity.
* @see getopt()
*/
int optopt;
/**
* Reset getopt.
* @see getopt()
*/
int optreset;
/**
* Argument associated with option.
* @see getopt()
*/
char *optarg;
char *getopt_place;
static char kGetoptEmsg[1];
static void getopt_print_badch(const char *s) {
char b1[512];
char b2[8] = " -- ";
b1[0] = 0;
if (program_invocation_name) {
strlcat(b1, program_invocation_name, sizeof(b1));
strlcat(b1, ": ", sizeof(b1));
}
strlcat(b1, s, sizeof(b1));
b2[4] = optopt;
b2[5] = '\n';
b2[6] = 0;
strlcat(b1, b2, sizeof(b1));
write(2, b1, strlen(b1));
static void getopt_print(const char *s) {
const char *prog;
char b[8] = " -- ?\n";
prog = program_invocation_short_name;
b[4] = optopt;
tinyprint(2, prog ? prog : "", prog ? ": " : "", s, b, NULL);
}
/**
@ -116,69 +87,74 @@ static void getopt_print_badch(const char *s) {
*/
int getopt(int nargc, char *const nargv[], const char *ostr) {
char *oli; /* option letter list index */
static bool once;
if (!once) {
if (!optglob.once) {
opterr = 1;
optind = 1;
getopt_place = kGetoptEmsg;
once = true;
optglob.place = optglob.emsg;
optglob.once = 1;
}
/*
* Some programs like cvs expect optind = 0 to trigger
* a reset of getopt.
*/
if (optind == 0) optind = 1;
if (optreset || *getopt_place == 0) { /* update scanning pointer */
if (!optind) optind = 1;
if (optreset || !*optglob.place) { /* update scanning pointer */
optreset = 0;
getopt_place = nargv[optind];
if (optind >= nargc || *getopt_place++ != '-') {
optglob.place = nargv[optind];
if (optind >= nargc || *optglob.place++ != '-') {
/* Argument is absent or is not an option */
getopt_place = kGetoptEmsg;
optglob.place = optglob.emsg;
return -1;
}
optopt = *getopt_place++;
if (optopt == '-' && *getopt_place == 0) {
optopt = *optglob.place++;
if (optopt == '-' && !*optglob.place) {
/* "--" => end of options */
++optind;
getopt_place = kGetoptEmsg;
optglob.place = optglob.emsg;
return -1;
}
if (optopt == 0) {
if (!optopt) {
/* Solitary '-', treat as a '-' option
if the program (eg su) is looking for it. */
getopt_place = kGetoptEmsg;
if (strchr(ostr, '-') == NULL) return -1;
optglob.place = optglob.emsg;
if (!strchr(ostr, '-')) return -1;
optopt = '-';
}
} else {
optopt = *getopt_place++;
optopt = *optglob.place++;
}
/* See if option letter is one the caller wanted... */
if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
if (*getopt_place == 0) ++optind;
if (opterr && *ostr != ':') getopt_print_badch("illegal option");
if (optopt == ':' || !(oli = strchr(ostr, optopt))) {
if (!*optglob.place) ++optind;
if (opterr && *ostr != ':') {
getopt_print("illegal option");
}
return BADCH;
}
/* Does this option need an argument? */
if (oli[1] != ':') {
/* don't need argument */
optarg = NULL;
if (*getopt_place == 0) ++optind;
optarg = 0;
if (!*optglob.place) ++optind;
} else {
/* Option-argument is either the rest of this argument or the
entire next argument. */
if (*getopt_place) {
optarg = getopt_place;
if (*optglob.place) {
optarg = optglob.place;
} else if (nargc > ++optind) {
optarg = nargv[optind];
} else {
/* option-argument absent */
getopt_place = kGetoptEmsg;
if (*ostr == ':') return BADARG;
if (opterr) getopt_print_badch("option requires an argument");
optglob.place = optglob.emsg;
if (*ostr == ':') {
return BADARG;
}
if (opterr) {
getopt_print("option requires an argument");
}
return BADCH;
}
getopt_place = kGetoptEmsg;
optglob.place = optglob.emsg;
++optind;
}
return optopt; /* return option letter */

View file

@ -4,11 +4,11 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
_Hide char *__crypt_des(const char *, const char *, char *);
_Hide char *__crypt_md5(const char *, const char *, char *);
_Hide char *__crypt_blowfish(const char *, const char *, char *);
_Hide char *__crypt_sha256(const char *, const char *, char *);
_Hide char *__crypt_sha512(const char *, const char *, char *);
char *__crypt_des(const char *, const char *, char *);
char *__crypt_md5(const char *, const char *, char *);
char *__crypt_blowfish(const char *, const char *, char *);
char *__crypt_sha256(const char *, const char *, char *);
char *__crypt_sha512(const char *, const char *, char *);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -23,9 +23,6 @@
/* Aborts after printing the nul-terminated string s[]. */
void nsync_panic_ (const char *s) {
char b[256], *p = b;
p = stpcpy (p, "panic: ");
p = stpcpy (p, s);
write (2, b, p - b);
tinyprint (2, "nsync panic: ", s, NULL);
notpossible;
}

View file

@ -6,7 +6,6 @@ PKGS += TOOL_BUILD
TOOL_BUILD_FILES := $(wildcard tool/build/*)
TOOL_BUILD_SRCS = $(filter %.c,$(TOOL_BUILD_FILES))
TOOL_BUILD_HDRS = $(filter %.h,$(TOOL_BUILD_FILES))
TOOL_BUILD_CTESTS = $(filter %.ctest,$(TOOL_BUILD_FILES))
TOOL_BUILD_BINS = \
$(TOOL_BUILD_COMS) \
@ -21,8 +20,6 @@ TOOL_BUILD_BINS = \
o/$(MODE)/tool/build/printf \
o/$(MODE)/tool/build/dd
TOOL_BUILD_CALCULATOR = o/$(MODE)/tool/build/calculator.com
TOOL_BUILD_OBJS = \
$(TOOL_BUILD_SRCS:%.c=o/$(MODE)/%.o)
@ -31,8 +28,7 @@ TOOL_BUILD_COMS = \
TOOL_BUILD_CHECKS = \
$(TOOL_BUILD).pkg \
$(TOOL_BUILD_HDRS:%=o/$(MODE)/%.ok) \
$(TOOL_BUILD_CTESTS:%=o/$(MODE)/%.ok)
$(TOOL_BUILD_HDRS:%=o/$(MODE)/%.ok)
TOOL_BUILD_DIRECTDEPS = \
DSP_CORE \
@ -80,12 +76,6 @@ o/$(MODE)/tool/build/build.pkg: \
$(TOOL_BUILD_OBJS) \
$(foreach x,$(TOOL_BUILD_DIRECTDEPS),$($(x)_A).pkg)
o/$(MODE)/%.ctest.ok: \
%.ctest \
$(TOOL_BUILD_CALCULATOR) \
$(VM)
@$(COMPILE) -AMKWIDES -wtT$@ $(VM) $(TOOL_BUILD_CALCULATOR) $<
o/$(MODE)/tool/build/%.com.dbg: \
$(TOOL_BUILD_DEPS) \
o/$(MODE)/tool/build/build.pkg \

View file

@ -1,760 +0,0 @@
#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 "dsp/tty/tty.h"
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/morton.h"
#include "libc/intrin/popcnt.h"
#include "libc/limits.h"
#include "libc/log/color.internal.h"
#include "libc/log/internal.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/math.h"
#include "libc/mem/arraylist2.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/rand.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/sig.h"
#include "libc/tinymath/emodl.h"
#include "libc/x/xsigaction.h"
#include "third_party/gdtoa/gdtoa.h"
#include "third_party/getopt/getopt.internal.h"
#define INT int128_t
#define FLOAT long double
#define EPSILON 1e-16l
#define BANNER \
"\
Reverse Polish Notation Calculator\n\
Copyright 2020 Justine Alexandra Roberts Tunney\n\
This is fast portable lightweight software. You have the freedom to build\n\
software just like it painlessly. See http://github.com/jart/cosmopolitan\n\
"
#define USAGE1 \
"SYNOPSIS\n\
\n\
Reverse Polish Notation Calculator\n\
\n\
USAGE\n\
\n"
#define USAGE2 \
" [FLAGS] [FILE...]\n\
\n\
FLAGS\n\
\n\
-h\n\
-? shows this information\n\
-i force interactive mode\n\
\n\
KEYBOARD SHORTCUTS\n\
\n\
CTRL-D Closes standard input\n\
CTRL-C Sends SIGINT to program\n\
CTRL-U Redraw line\n\
CTRL-L Redraw display\n\
\n\
FUNCTIONS\n\
\n"
#define USAGE3 \
"\n\
EXAMPLES\n\
\n\
calculator.com\n\
40 2 +\n\
42\n\
\n\
echo '2 2 + . cr' | calculator.com\n\
4\n\
\n\
calculator.com <<EOF\n\
true assert\n\
-1 ~ 0 = assert\n\
3 2 / 1.5 = assert\n\
81 3 // 27 = assert\n\
2 8 ** 256 = assert\n\
pi cos -1 = assert\n\
pi sqrt pi sqrt * pi - abs epsilon < assert\n\
nan isnormal ! assert\n\
0b1010101 0b0110101 ^ 0b1100000 = assert\n\
0b1010101 popcnt 4 = assert\n\
EOF\n\
\n\
CONTACT\n\
\n\
Justine Tunney <jtunney@gmail.com>\n\
https://github.com/jart/cosmooplitan\n\
\n\
"
#define CTRL(C) ((C) ^ 0100)
#define Fatal(...) Log(kFatal, __VA_ARGS__)
#define Warning(...) Log(kWarning, __VA_ARGS__)
enum Severity {
kFatal,
kWarning,
};
enum Exception {
kUnderflow = 1,
kDivideError,
};
struct Bytes {
size_t i, n;
char *p;
};
struct History {
size_t i, n;
struct Bytes *p;
};
struct Value {
enum Type {
kInt,
kFloat,
} t;
union {
INT i;
FLOAT f;
};
};
struct Function {
const char sym[16];
void (*fun)(void);
const char *doc;
};
jmp_buf thrower;
const char *file;
struct Bytes token;
struct History history;
struct Value stack[128];
int sp, comment, line, column, interactive;
uint32_t gray(uint32_t x) {
return x ^ (x >> 1);
}
uint32_t ungray(uint32_t x) {
x ^= x >> 16;
x ^= x >> 8;
x ^= x >> 4;
x ^= x >> 2;
x ^= x >> 1;
return x;
}
INT Popcnt(INT x) {
uint128_t word = x;
return popcnt(word >> 64) + popcnt(word);
}
char *Repr(struct Value x) {
static char buf[64];
if (x.t == kFloat) {
g_xfmt_p(buf, &x.f, 16, sizeof(buf), 0);
} else {
sprintf(buf, "%jjd", x.i);
}
return buf;
}
char *ReprStack(void) {
int i, j, l;
char *s, *p;
static char buf[80];
p = memset(buf, 0, sizeof(buf));
for (i = 0; i < sp; ++i) {
s = Repr(stack[i]);
l = strlen(s);
if (p + l + 2 > buf + sizeof(buf)) break;
p = mempcpy(p, s, l);
*p++ = ' ';
}
return buf;
}
void ShowStack(void) {
if (interactive) {
printf("\r\e[K");
fputs(ReprStack(), stdout);
}
}
void Cr(FILE *f) {
fputs(interactive || IsWindows() ? "\r\n" : "\n", f);
}
void Log(enum Severity l, const char *fmt, ...) {
va_list va;
const char *severity[] = {"FATAL", "WARNING"};
if (interactive) fflush(/* key triggering throw not echo'd yet */ stdout);
fprintf(stderr, "%s:%d:%d:%s: ", file, line + 1, column, severity[l & 1]);
va_start(va, fmt);
vfprintf(stderr, fmt, va);
va_end(va);
Cr(stderr);
if (l == kFatal) exit(EXIT_FAILURE);
if (interactive) ShowStack();
}
void __on_arithmetic_overflow(void) {
Warning("arithmetic overflow");
}
void OnDivideError(void) {
longjmp(thrower, kDivideError);
}
struct Value Push(struct Value x) {
if (sp >= ARRAYLEN(stack)) Fatal("stack overflow");
return (stack[sp++] = x);
}
struct Value Pop(void) {
if (sp) {
return stack[--sp];
} else {
longjmp(thrower, kUnderflow);
}
}
INT Popi(void) {
struct Value x = Pop();
return x.t == kInt ? x.i : x.f;
}
void Pushi(INT i) {
struct Value x;
x.t = kInt;
x.i = i;
Push(x);
}
FLOAT Popf(void) {
struct Value x = Pop();
return x.t == kInt ? x.i : x.f;
}
void Pushf(FLOAT f) {
struct Value x;
x.t = kFloat;
x.f = f;
Push(x);
}
void OpDrop(void) {
Pop();
}
void OpDup(void) {
Push(Push(Pop()));
}
void OpExit(void) {
exit(Popi());
}
void OpSrand(void) {
srand(Popi());
}
void OpEmit(void) {
fputwc(Popi(), stdout);
}
void OpCr(void) {
Cr(stdout);
}
void OpPrint(void) {
printf("%s ", Repr(Pop()));
}
void OpComment(void) {
comment = true;
}
void Glue0f(FLOAT fn(void)) {
Pushf(fn());
}
void Glue0i(INT fn(void)) {
Pushi(fn());
}
void Glue1f(FLOAT fn(FLOAT)) {
Pushf(fn(Popf()));
}
void Glue1i(INT fn(INT)) {
Pushi(fn(Popi()));
}
void OpSwap(void) {
struct Value a, b;
b = Pop();
a = Pop();
Push(b);
Push(a);
}
void OpOver(void) {
struct Value a, b;
b = Pop();
a = Pop();
Push(a);
Push(b);
Push(a);
}
void OpKey(void) {
wint_t c;
ttyraw(kTtyCursor | kTtySigs | kTtyLfToCrLf);
c = fgetwc(stdin);
ttyraw(-1);
if (c != -1) Pushi(c);
}
void OpAssert(void) {
if (!Popi()) Fatal("assert failed");
}
void OpExpect(void) {
if (!Popi()) Warning("expect failed");
}
void OpMeminfo(void) {
OpCr();
OpCr();
fflush(stdout);
_meminfo(fileno(stdout));
}
void Glue2f(FLOAT fn(FLOAT, FLOAT)) {
FLOAT x, y;
y = Popf();
x = Popf();
Pushf(fn(x, y));
}
void Glue2i(INT fn(INT, INT)) {
INT x, y;
y = Popi();
x = Popi();
Pushi(fn(x, y));
}
void Glue1g(FLOAT fnf(FLOAT), INT fni(INT)) {
struct Value x;
x = Pop();
switch (x.t) {
case kInt:
Pushi(fni(x.i));
break;
case kFloat:
Pushf(fnf(x.f));
break;
default:
Warning("type mismatch");
}
}
void Glue2g(FLOAT fnf(FLOAT, FLOAT), INT fni(INT, INT)) {
struct Value x, y;
y = Pop();
x = Pop();
if (x.t == kInt && y.t == kInt) {
Pushi(fni(x.i, y.i));
} else if (x.t == kFloat && y.t == kFloat) {
Pushf(fnf(x.f, y.f));
} else if (x.t == kInt && y.t == kFloat) {
Pushf(fnf(x.i, y.f));
} else if (x.t == kFloat && y.t == kInt) {
Pushf(fnf(x.f, y.i));
} else {
Warning("type mismatch");
}
}
#define LB {
#define RB }
#define SEMI ;
#define FNTYPEi INT
#define FNTYPEf FLOAT
#define FORM(F) LB F SEMI RB
#define FNPL0(T) void
#define FNPL1(T) FNTYPE##T x
#define FNPL2(T) FNTYPE##T x, FNTYPE##T y
#define FNDEF(A, T, S, C) FNTYPE##T Fn##S##T(FNPL##A(T)) FORM(return C)
#define FNDEFf(A, S, C) FNDEF(A, f, S, C)
#define FNDEFi(A, S, C) FNDEF(A, i, S, C)
#define FNDEFg(A, S, C) FNDEF(A, f, S, C) FNDEF(A, i, S, C)
#define OPDEF(A, T, S, C) void Op##S(void) FORM(Glue##A##T(Fn##S##T))
#define OPDEFf(A, S, C) OPDEF(A, f, S, C)
#define OPDEFi(A, S, C) OPDEF(A, i, S, C)
#define OPDEFg(A, S, C) void Op##S(void) FORM(Glue##A##g(Fn##S##f, Fn##S##i))
#define M(A, T, N, S, C, D) FNDEF##T(A, S, C) OPDEF##T(A, S, C)
#include "tool/build/calculator.inc"
#undef M
const struct Function kFunctions[] = {
{".", OpPrint, "pops prints value repr"},
{"#", OpComment, "line comment"},
#define M(A, T, N, S, C, D) {N, Op##S, D},
#include "tool/build/calculator.inc"
#undef M
{"dup", OpDup, "pushes copy of last item on stack"},
{"drop", OpDrop, "pops and discards"},
{"swap", OpSwap, "swaps last two items on stack"},
{"over", OpOver, "pushes second item on stack"},
{"cr", OpCr, "prints newline"},
{"key", OpKey, "reads and pushes unicode character from keyboard"},
{"emit", OpEmit, "pops and writes unicode character to output"},
{"assert", OpAssert, "crashes if top of stack isn't nonzero"},
{"expect", OpExpect, "prints warning if top of stack isn't nonzero"},
{"meminfo", OpMeminfo, "prints memory mappings"},
{"exit", OpExit, "exits program with status"},
};
bool CallFunction(const char *sym) {
int i;
char s[16];
strncpy(s, sym, sizeof(s));
for (i = 0; i < ARRAYLEN(kFunctions); ++i) {
if (memcmp(kFunctions[i].sym, s, sizeof(s)) == 0) {
kFunctions[i].fun();
return true;
}
}
return false;
}
volatile const char *literal_;
bool ConsumeLiteral(const char *literal) {
bool r;
char *e;
struct Value x;
literal_ = literal;
errno = 0;
x.t = kInt;
x.i = strtoi128(literal, &e, 0);
if (*e) {
x.t = kFloat;
x.f = strtod(literal, &e);
r = !(!e || *e);
} else if (errno == ERANGE) {
r = false;
} else {
r = true;
}
Push(x);
return r;
}
void ConsumeToken(void) {
enum Exception ex;
if (!token.i) return;
token.p[token.i] = 0;
token.i = 0;
if (history.i) history.p[history.i - 1].i = 0;
if (comment) return;
if (_startswith(token.p, "#!")) return;
switch (setjmp(thrower)) {
default:
if (CallFunction(token.p)) return;
if (ConsumeLiteral(token.p)) return;
Warning("bad token: %`'s", token.p);
break;
case kUnderflow:
Warning("stack underflow");
break;
case kDivideError:
Warning("divide error");
break;
}
}
void CleanupRepl(void) {
if (sp && interactive) {
Cr(stdout);
}
}
void AppendByte(struct Bytes *a, char b) {
APPEND(&a->p, &a->i, &a->n, &b);
}
void AppendHistory(void) {
struct Bytes line;
if (interactive) {
bzero(&line, sizeof(line));
APPEND(&history.p, &history.i, &history.n, &line);
}
}
void AppendLine(char b) {
if (interactive) {
if (!history.i) AppendHistory();
AppendByte(&history.p[history.i - 1], b);
}
}
void Echo(int c) {
if (interactive) {
fputc(c, stdout);
}
}
void Backspace(int c) {
struct Bytes *line;
if (interactive) {
if (history.i) {
line = &history.p[history.i - 1];
if (line->i && token.i) {
do {
line->i--;
token.i--;
} while (line->i && token.i && (line->p[line->i] & 0x80));
fputs("\e[D \e[D", stdout);
}
}
}
}
void NewLine(void) {
line++;
column = 0;
comment = false;
if (interactive) {
Cr(stdout);
AppendHistory();
ShowStack();
}
}
void KillLine(void) {
if (interactive) {
if (history.i) {
history.p[history.i - 1].i--;
}
}
}
void ClearLine(void) {
if (interactive) {
if (token.i) sp = 0;
ShowStack();
}
}
void RedrawDisplay(void) {
int i;
struct Bytes *line;
if (interactive) {
printf("\e[H\e[2J%s", BANNER);
ShowStack();
if (history.i) {
line = &history.p[history.i - 1];
for (i = 0; i < line->i; ++i) {
fputc(line->p[i], stdout);
}
}
}
}
void GotoStartOfLine(void) {
if (interactive) {
printf("\r");
}
}
void GotoEndOfLine(void) {
}
void GotoPrevLine(void) {
}
void GotoNextLine(void) {
}
void GotoPrevChar(void) {
}
void GotoNextChar(void) {
}
void Calculator(FILE *f) {
int c;
while (!feof(f)) {
switch ((c = getc(f))) {
case -1:
case CTRL('D'):
goto Done;
case CTRL('@'):
break;
case ' ':
column++;
Echo(c);
AppendLine(c);
ConsumeToken();
break;
case '\t':
column = ROUNDUP(column, 8);
Echo(c);
AppendLine(c);
ConsumeToken();
break;
case '\r':
case '\n':
ConsumeToken();
NewLine();
break;
case CTRL('A'):
GotoStartOfLine();
break;
case CTRL('E'):
GotoEndOfLine();
break;
case CTRL('P'):
GotoPrevLine();
break;
case CTRL('N'):
GotoNextLine();
break;
case CTRL('B'):
GotoPrevChar();
break;
case CTRL('F'):
GotoNextChar();
break;
case CTRL('L'):
RedrawDisplay();
break;
case CTRL('U'):
ClearLine();
break;
case CTRL('K'):
KillLine();
break;
case CTRL('?'):
case CTRL('H'):
Backspace(c);
break;
default:
column++;
/* fallthrough */
case 0x80 ... 0xff:
Echo(c);
AppendLine(c);
AppendByte(&token, c);
break;
}
fflush(/* needed b/c this is event loop */ stdout);
}
Done:
CleanupRepl();
}
int Calculate(const char *path) {
FILE *f;
file = path;
line = column = 0;
if (!(f = fopen(file, "r"))) Fatal("file not found: %s", file);
Calculator(f);
return fclose(f);
}
void CleanupTerminal(void) {
ttyraw(-1);
}
void StartInteractive(void) {
if (!interactive && !__nocolor && isatty(fileno(stdin)) &&
isatty(fileno(stdout)) && !__nocolor) {
interactive = true;
}
errno = 0;
if (interactive) {
fputs(BANNER, stdout);
fflush(/* needed b/c entering tty mode */ stdout);
ttyraw(kTtyCursor | kTtySigs);
atexit(CleanupTerminal);
}
}
void PrintUsage(int rc, FILE *f) {
char c;
int i, j;
fprintf(f, "%s %s%s", USAGE1, program_invocation_name, USAGE2);
for (i = 0; i < ARRAYLEN(kFunctions); ++i) {
fputs(" ", f);
for (j = 0; j < ARRAYLEN(kFunctions[i].sym); ++j) {
c = kFunctions[i].sym[j];
fputc(c ? c : ' ', f);
}
fprintf(f, " %s\n", kFunctions[i].doc);
}
fputs(USAGE3, f);
exit(rc);
}
void GetOpts(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "?hi")) != -1) {
switch (opt) {
case 'i':
interactive = true;
break;
case 'h':
case '?':
PrintUsage(EXIT_SUCCESS, stdout);
default:
PrintUsage(EX_USAGE, stderr);
}
}
}
int main(int argc, char *argv[]) {
int i, rc;
ShowCrashReports();
GetOpts(argc, argv);
xsigaction(SIGFPE, OnDivideError, 0, 0, 0);
if (optind == argc) {
file = "/dev/stdin";
StartInteractive();
Calculator(stdin);
return fclose(stdin);
} else {
for (i = optind; i < argc; ++i) {
if (Calculate(argv[i]) == -1) {
return -1;
}
}
}
return 0;
}

View file

@ -1,91 +0,0 @@
# INTEGER
2 3 + 5 = assert
3 2 + 5 = assert
5 2 - 3 = assert
2 5 - -3 = assert
81 3 / 27 = assert
81 3 // 27 = assert
2 8 ** 256 = assert
17 10 % 7 = assert
17 10 fmod 7 = assert
# FLOATING POINT
.1 .2 + .3 - abs epsilon < assert
pi sqrt pi sqrt * pi - abs epsilon < assert
3 2 / 1.5 = assert
pi pi = assert
pi cos -1 = assert
pi 2 / sin 1 = assert
81 3 / 27 = assert
inf isinf assert
inf isnormal ! assert
nan isnormal ! assert
1 0 / isnormal ! assert
0 signbit ! assert
-.5 round -1 = assert
-.5 floor -1 = assert
-.5 rint dup 0 = assert signbit assert
-.5 nearbyint dup 0 = assert signbit assert
-.5 ceil dup 0 = assert signbit assert
-.5 trunc dup 0 = assert signbit assert
0 0 / dup isnan assert signbit assert # is this right?
1 0 / dup isinf assert signbit ! assert # is this right?
nan nan != assert # is this right?
# -nan -nan != assert # is this right?
inf inf = assert # is this right?
-inf -inf = assert # is this right?
# BIT ARITHMETIC
-1 ~ 0 = assert
0 0x7fffffffffffffffffffffffffffffff - -0x7fffffffffffffffffffffffffffffff = assert
0b1010101 popcnt 4 = assert
0b1010101 0b0110101 ^ 0b1100000 = assert
0b1010101 0b0110101 | 0b1110101 = assert
0b1010101 0b0110101 & 0b0010101 = assert
0b1010101 1 >> 0b000101010 = assert
0b1010101 2 >> 0b000010101 = assert
0b1010101 1 << 0b010101010 = assert
0b1010101 2 << 0b101010100 = assert
# BOOLEAN
true assert
false ! assert
true ! ! assert
true true && assert
true false && ! assert
false true && ! assert
true false && ! assert
false true && ! assert
true true || assert
false true || assert
true false || assert
false false || ! assert
4 5 < assert
5 4 < ! assert
-5 4 < assert
5 5 < ! assert
5 5 <= assert
5 4 > assert
4 5 > ! assert
4 -5 > assert
5 5 > ! assert
5 5 >= assert
# MISC
1 abs 1 = assert
-1 abs 1 = assert
-1 1 max 1 = assert
1 -1 max 1 = assert
1 2 max 2 = assert
-1 1 min -1 = assert
1 -1 min -1 = assert
1 2 min 1 = assert
rand64 rand64 rand64 rand64 != != && assert
# HEX SIGN
-0x80000000 -2147483648 = assert
0x80000000 2147483648 = assert
0x80000001 2147483649 = assert
0xffffffff 4294967295 = assert
0x100000000 4294967296 = assert
-0x100000000 -4294967296 = assert

View file

@ -1,100 +0,0 @@
M(2, g, "+", Add, x + y, "add")
M(2, g, "-", Sub, x - y, "sub")
M(2, g, "*", Mul, x *y, "multiply")
M(2, f, "/", Div, x / y, "division")
M(2, i, "%", Rem, x % y, "integer remainder")
M(2, i, "//", Idiv, x / y, "integer division")
M(2, g, "**", Expo, powl(x, y), "exponentiation")
M(1, i, "~", Not, ~x, "bitwise not")
M(2, i, "^", Xor, x ^ y, "bitwise xor")
M(2, i, "|", Or, x | y, "bitwise or")
M(2, i, "&", And, x &y, "bitwise and")
M(2, i, ">>", Shr, x >> y, "shift right")
M(2, i, "<<", Shl, x << y, "shift left")
M(1, i, "!", LogicalNot, !x, "logical not")
M(2, i, "||", LogicalOr, x || y, "logical or")
M(2, i, "&&", LogicalAnd, x &&y, "logical and")
M(2, g, "=", Equal1, x == y, "equal to")
M(2, g, "!=", Notequal, x != y, "not equal to")
M(2, g, "<", LessThan, x < y, "less than")
M(2, g, ">", GreaterThan, x > y, "greater than")
M(2, g, "<=", LessThanEqual, x <= y, "less than or equal to")
M(2, g, ">=", GreaterThanEqual, x >= y, "greater than or equal to")
M(1, i, "gray", Gray, gray(x), "gray coding")
M(1, i, "ungray", Ungray, ungray(x), "inverse gray coding")
M(1, i, "popcnt", Popcnt, Popcnt(x), "count bits")
M(1, g, "abs", Abs, fabsl(x), "absolute value")
M(2, g, "min", Min, fminl(x, y), "pops two values and pushes minimum")
M(2, g, "max", Max, fmaxl(x, y), "pops two values and pushes maximum")
M(2, g, "fmod", Fmod, fmodl(x, y), "trunc remainder")
M(2, g, "emod", Emod, emodl(x, y), "euclidean remainder")
M(2, g, "remainder", Remainder, remainderl(x, y), "rint remainder")
M(2, g, "hypot", Hypot, hypotl(x, y), "euclidean distance")
M(0, i, "false", False, 0, "0")
M(0, i, "true", True, 1, "1")
M(0, i, "intmin", IntMin, INT128_MIN, "native integer minimum")
M(0, i, "intmax", IntMax, INT128_MAX, "native integer maximum")
M(0, f, "e", Euler, M_E, "𝑒")
M(0, f, "pi", Fldpi, M_PI, "π")
M(0, f, "epsilon", Epsilon, EPSILON, "ɛ")
M(0, f, "inf", Inf, INFINITY, "")
M(0, f, "nan", Nan, NAN, "NAN")
M(0, f, "-0", Negzero, -0., "wut")
M(0, f, "l2t", Fldl2t, M_LOG2_10, "log₂10")
M(0, f, "lg2", Fldlg2, M_LOG10_2, "log₁₀2")
M(0, f, "ln2", Fldln2, M_LN2, "logₑ2")
M(0, f, "l2e", Fldl2e, M_LOG2E, "logₑ10")
M(2, f, "nextafter", Nextafter, nextafterl(x, y), "next ulp")
M(1, f, "significand", Significand, significandl(x), "mantissa")
M(1, f, "sqrt", Sqrt, sqrtl(x), "√𝑥")
M(1, f, "exp", Exp, expl(x), "𝑒ˣ")
M(1, g, "expm1", Expm1, expm1l(x), "𝑒ˣ-1")
M(1, g, "exp2", Exp2, exp2l(x), "")
M(1, g, "exp10", Exp10, exp10l(x), "10ˣ")
M(2, g, "ldexp", Ldexp, ldexpl(x, y), "𝑥×")
M(1, f, "log", Log, logl(x), "logₑ𝑥")
M(1, g, "log2", Log2, log2l(x), "log₂𝑥")
M(1, g, "log10", Log10, log10l(x), "log₁₀𝑥")
M(1, g, "ilogb", Ilogb, ilogbl(x), "exponent")
M(1, g, "sin", Sin, sinl(x), "sine")
M(1, g, "cos", Cos, cosl(x), "cosine")
M(1, g, "tan", Tan, tanl(x), "tangent")
M(1, g, "asin", Asin, asinl(x), "arcsine")
M(1, g, "acos", Acos, acosl(x), "arccosine")
M(1, g, "atan", Atan, atanl(x), "arctangent")
M(2, g, "atan2", Atan2, atan2l(x, y), "arctangent of 𝑥/𝑦")
M(1, g, "sinh", Sinh, sinhl(x), "hyperbolic sine")
M(1, g, "cosh", Cosh, coshl(x), "hyperbolic cosine")
M(1, g, "tanh", Tanh, tanhl(x), "hyperbolic tangent")
M(1, g, "asinh", Asinh, asinhl(x), "hyperbolic arcsine")
M(1, g, "acosh", Acosh, acoshl(x), "hyperbolic arccosine")
M(1, g, "atanh", Atanh, atanhl(x), "hyperbolic arctangent")
M(1, g, "round", Round, roundl(x), "round away from zero")
M(1, g, "trunc", Trunc, truncl(x), "round towards zero")
M(1, g, "rint", Rint, rintl(x), "round to even")
M(1, g, "nearbyint", Nearbyint, nearbyintl(x), "round to nearest integer")
M(1, g, "ceil", Ceil, ceill(x), "smallest integral not less than 𝑥")
M(1, g, "floor", Floor, floorl(x), "largest integral not greater than 𝑥")
M(1, f, "isnan", Isnan, isnan(x), "returns true if 𝑥=NAN")
M(1, f, "isinf", Isinf, isinf(x), "returns true if 𝑥=INFINITY")
M(1, f, "signbit", Signbit, signbit(x), "clears all bits but sign bit")
M(1, f, "isfinite", Isfinite, isfinite(x), "returns true if 𝑥≠INFINITY")
M(1, f, "isnormal", Isnormal, isnormal(x), "returns true if not denormal")
M(1, f, "fpclassify", Fpclassify, fpclassify(x),
"nan=0,inf=1,zero=2,subnorm=3,normal=4")
M(0, i, "rand", Rand, rand(), "deterministic random number")
M(0, i, "rand64", _Rand64, _rand64(), "64-bit random number")

View file

@ -21,6 +21,7 @@
#include "libc/fmt/conv.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "third_party/getopt/getopt.internal.h"
@ -33,42 +34,21 @@ SYNOPSIS\n\
\n\
FLAGS\n\
\n\
-?\n\
-h help\n\
\n"
const char *prog;
nullterminated() static void Print(int fd, const char *s, ...) {
va_list va;
char buf[2048];
va_start(va, s);
buf[0] = 0;
do {
strlcat(buf, s, sizeof(buf));
} while ((s = va_arg(va, const char *)));
write(fd, buf, strlen(buf));
va_end(va);
}
static wontreturn void SysExit(const char *path, const char *func) {
const char *errstr;
if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN";
Print(2, path, ": ", func, " failed with ", errstr, "\n", NULL);
exit(1);
}
static wontreturn void PrintUsage(int fd, int rc) {
Print(fd, "USAGE\n\n ", program_invocation_name, USAGE, NULL);
tinyprint(fd, "USAGE\n\n ", prog, USAGE, NULL);
exit(rc);
}
static void GetOpts(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "?h")) != -1) {
while ((opt = getopt(argc, argv, "h")) != -1) {
switch (opt) {
case 'h':
case '?':
PrintUsage(1, 0);
default:
PrintUsage(2, 1);
@ -79,18 +59,22 @@ static void GetOpts(int argc, char *argv[]) {
int main(int argc, char *argv[]) {
int i, mode;
char buf[PATH_MAX], *endptr;
prog = argv[0];
if (!prog) prog = "chmod";
GetOpts(argc, argv);
if (argc - optind < 2) {
PrintUsage(2, 1);
tinyprint(2, prog, ": missing operand\n", NULL);
exit(1);
}
mode = strtol(argv[optind], &endptr, 8) & 07777;
if (*endptr) {
Print(2, "chmod: invalid mode octal\n", NULL);
tinyprint(2, prog, ": invalid mode octal\n", NULL);
exit(1);
}
for (i = optind + 1; i < argc; ++i) {
if (chmod(argv[i], mode) == -1) {
SysExit(argv[i], "chmod");
perror(argv[i]);
exit(1);
}
}
return 0;

View file

@ -24,6 +24,7 @@
#include "libc/fmt/fmt.h"
#include "libc/fmt/libgen.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/mem/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
@ -91,16 +92,14 @@ bool IsSymlink(const char *path) {
return res;
}
wontreturn void PrintUsage(int rc, FILE *f) {
fputs("usage: ", f);
fputs(prog, f);
fputs(USAGE, f);
wontreturn void PrintUsage(int rc, int fd) {
tinyprint(fd, "USAGE\n\n ", prog, USAGE, NULL);
exit(rc);
}
void GetOpts(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "?hfnaprR")) != -1) {
while ((opt = getopt(argc, argv, "hfnaprR")) != -1) {
switch (opt) {
case 'f':
force = true;
@ -118,10 +117,9 @@ void GetOpts(int argc, char *argv[]) {
flags |= COPYFILE_PRESERVE_TIMESTAMPS;
break;
case 'h':
case '?':
PrintUsage(EXIT_SUCCESS, stdout);
PrintUsage(0, 1);
default:
PrintUsage(EX_USAGE, stderr);
PrintUsage(1, 2);
}
}
}
@ -146,8 +144,7 @@ int Visit(const char *fpath, const struct stat *sb, int tflag,
Cp(srcfile, dstfile);
return 0;
default:
fputs(fpath, stderr);
fputs(": can't handle file type\n", stderr);
tinyprint(2, fpath, ": bad file type\n", NULL);
exit(1);
}
}
@ -157,7 +154,7 @@ char *Join(const char *a, const char *b) {
n = strlen(a);
m = strlen(b);
if (n + 1 + m + 1 > sizeof(dstfile)) {
fputs("error: cp: path too long\n", stderr);
tinyprint(2, prog, ": path too long\n", NULL);
exit(1);
}
stpcpy(stpcpy(stpcpy(dstfile, a), "/"), b);
@ -191,8 +188,7 @@ void Cp(char *src, char *dst) {
basename(dst);
if (IsDirectory(src)) {
if (!recursive) {
fputs(prog, stderr);
fputs(": won't copy directory without -r flag.\n", stderr);
tinyprint(2, prog, ": won't copy directory without -r flag\n", NULL);
exit(1);
}
strcpy(dstdir, dst);
@ -208,10 +204,7 @@ void Cp(char *src, char *dst) {
strcpy(srcdir, "");
}
if (nftw(src, Visit, 20, 0) == -1) {
fputs(prog, stderr);
fputs(": nftw failed: ", stderr);
fputs(_strerdoc(errno), stderr);
fputs("\n", stderr);
perror(src);
exit(1);
}
return;
@ -219,37 +212,49 @@ void Cp(char *src, char *dst) {
if (IsDirectory(dst)) {
dst = Join(dst, basename(src));
}
if (!force && access(dst, W_OK) == -1 && errno != ENOENT) goto OnFail;
strcpy(mkbuf, dst);
if (makedirs(dirname(mkbuf), 0755) == -1) goto OnFail;
if (IsSymlink(src)) {
if ((rc = readlink(src, linkbuf, sizeof(linkbuf) - 1)) == -1) goto OnFail;
linkbuf[rc] = 0;
if (symlink(linkbuf, dst) == -1) goto OnFail;
} else {
if (!MovePreservingDestinationInode(src, dst)) goto OnFail;
if (!force && access(dst, W_OK) == -1 && errno != ENOENT) {
perror(dst);
exit(1);
}
strcpy(mkbuf, dst);
if (makedirs((s = dirname(mkbuf)), 0755) == -1) {
perror(s);
exit(1);
}
if (IsSymlink(src)) {
if ((rc = readlink(src, linkbuf, sizeof(linkbuf) - 1)) == -1) {
perror(src);
exit(1);
}
linkbuf[rc] = 0;
if (symlink(linkbuf, dst) == -1) {
perror(dst);
exit(1);
}
} else {
if (!MovePreservingDestinationInode(src, dst)) {
perror(src);
exit(1);
}
}
return;
OnFail:
s = _strerdoc(errno);
fputs(prog, stderr);
fputs(": ", stderr);
fputs(src, stderr);
fputs(" ", stderr);
fputs(dst, stderr);
fputs(": ", stderr);
fputs(s, stderr);
fputs("\n", stderr);
exit(1);
}
int main(int argc, char *argv[]) {
int i;
prog = argc > 0 ? argv[0] : "cp.com";
prog = argv[0];
if (!prog) prog = "cp";
GetOpts(argc, argv);
if (argc - optind < 2) PrintUsage(EX_USAGE, stderr);
if (argc - optind < 2) {
tinyprint(2, prog, ": missing operand\n", NULL);
exit(1);
}
for (i = optind; i < argc - 1; ++i) {
Cp(argv[i], argv[argc - 1]);
}
return 0;
}

View file

@ -73,32 +73,20 @@ static const char *epath;
static Elf64_Xword symcount;
static const Elf64_Ehdr *elf;
nullterminated() static void Print(int fd, const char *s, ...) {
va_list va;
char buf[2048];
va_start(va, s);
buf[0] = 0;
do {
strlcat(buf, s, sizeof(buf));
} while ((s = va_arg(va, const char *)));
write(fd, buf, strlen(buf));
va_end(va);
}
static wontreturn void Die(const char *reason) {
Print(2, epath, ": ", reason, "\n", NULL);
tinyprint(2, epath, ": ", reason, "\n", NULL);
exit(1);
}
static wontreturn void SysExit(const char *func) {
const char *errstr;
if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN";
Print(2, epath, ": ", func, " failed with ", errstr, "\n", NULL);
tinyprint(2, epath, ": ", func, " failed with ", errstr, "\n", NULL);
exit(1);
}
static wontreturn void PrintUsage(int fd, int exitcode) {
Print(fd, "\n\
tinyprint(fd, "\n\
NAME\n\
\n\
Cosmopolitan Object Fixer\n\
@ -106,7 +94,7 @@ NAME\n\
SYNOPSIS\n\
\n\
",
program_invocation_name, " [FLAGS] OBJECT...\n\
program_invocation_name, " [FLAGS] OBJECT...\n\
\n\
DESCRIPTION\n\
\n\
@ -124,7 +112,7 @@ FLAGS\n\
-c checks only mode\n\
\n\
",
NULL);
NULL);
exit(exitcode);
}
@ -143,10 +131,10 @@ static void GetOpts(int argc, char *argv[]) {
}
}
if (optind == argc) {
Print(2,
"error: no elf object files specified\n"
"run ",
program_invocation_name, " -h for usage\n", NULL);
tinyprint(2,
"error: no elf object files specified\n"
"run ",
program_invocation_name, " -h for usage\n", NULL);
exit(1);
}
}
@ -184,11 +172,11 @@ static void CheckPrivilegedCrossReferences(void) {
if (~shdr->sh_flags & SHF_EXECINSTR) continue; // data reference
if ((secname = GetElfString(elf, esize, secstrs, shdr->sh_name)) &&
strcmp(".privileged", secname)) {
Print(2, epath,
": code in .privileged section "
"references symbol '",
GetElfString(elf, esize, symstrs, syms[x].st_name),
"' in unprivileged code section '", secname, "'\n", NULL);
tinyprint(2, epath,
": code in .privileged section "
"references symbol '",
GetElfString(elf, esize, symstrs, syms[x].st_name),
"' in unprivileged code section '", secname, "'\n", NULL);
exit(1);
}
}

View file

@ -289,7 +289,8 @@ void Decompress(const char *inpath) {
int main(int argc, char *argv[]) {
int i;
prog = argc > 0 ? argv[0] : "cp.com";
prog = argv[0];
if (!prog) prog = "gzip";
GetOpts(argc, argv);
if (opt_decompress) {
if (optind == argc) {

View file

@ -52,7 +52,7 @@ void PrintUsage(int rc, FILE *f) {
void GetOpts(int argc, char *argv[]) {
int opt;
bits_ = 64;
while ((opt = getopt(argc, argv, "?hbs")) != -1) {
while ((opt = getopt(argc, argv, "hbs")) != -1) {
switch (opt) {
case 's':
succinct_ = true;
@ -60,7 +60,6 @@ void GetOpts(int argc, char *argv[]) {
case 'b':
bits_ = atoi(optarg);
break;
case '?':
case 'h':
PrintUsage(EXIT_SUCCESS, stdout);
default:

View file

@ -8,14 +8,9 @@
*/
#endif
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ex.h"
#include "libc/x/x.h"
#include "third_party/getopt/getopt.internal.h"
#define USAGE \
@ -30,19 +25,19 @@ FLAGS\n\
const char *prog;
wontreturn void PrintUsage(int rc, FILE *f) {
fputs("Usage: ", f);
fputs(prog, f);
fputs(USAGE, f);
wontreturn void PrintUsage(int rc, int fd) {
tinyprint(fd, "USAGE\n\n ", prog, USAGE, NULL);
exit(rc);
}
int main(int argc, char *argv[]) {
int i, mode = 0755;
int (*mkdirp)(const char *, unsigned) = mkdir;
prog = argc > 0 ? argv[0] : "mkdir.com";
while ((i = getopt(argc, argv, "?hpm:")) != -1) {
prog = argv[0];
if (!prog) prog = "mkdir";
while ((i = getopt(argc, argv, "hpm:")) != -1) {
switch (i) {
case 'p':
mkdirp = makedirs;
@ -50,31 +45,21 @@ int main(int argc, char *argv[]) {
case 'm':
mode = strtol(optarg, 0, 8);
break;
case '?':
case 'h':
PrintUsage(0, stdout);
PrintUsage(0, 1);
default:
PrintUsage(EX_USAGE, stderr);
PrintUsage(1, 2);
}
}
if (optind == argc) {
fputs(prog, stderr);
fputs(": missing argument\n", stderr);
fputs("Try '", stderr);
fputs(prog, stderr);
fputs(" -h' for more information.\n", stderr);
tinyprint(2, prog, ": missing operand\n", NULL);
exit(1);
}
for (i = optind; i < argc; ++i) {
if (mkdirp(argv[i], mode) == -1) {
fputs(prog, stderr);
fputs(": cannot create directory '", stderr);
fputs(argv[i], stderr);
fputs("' ", stderr);
fputs(_strerdoc(errno), stderr);
fputc('\n', stderr);
perror(argv[i]);
exit(1);
}
}

View file

@ -62,27 +62,15 @@ char linkbuf[PATH_MAX];
void Mv(char *, char *);
nullterminated() void Print(int fd, const char *s, ...) {
va_list va;
char buf[2048];
va_start(va, s);
buf[0] = 0;
do {
strlcat(buf, s, sizeof(buf));
} while ((s = va_arg(va, const char *)));
write(fd, buf, strlen(buf));
va_end(va);
}
wontreturn void Die(const char *path, const char *reason) {
Print(2, path, ": ", reason, "\n", NULL);
tinyprint(2, path, ": ", reason, "\n", NULL);
exit(1);
}
wontreturn void SysExit(const char *path, const char *func) {
wontreturn void SysDie(const char *path, const char *func) {
const char *errstr;
if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN";
Print(2, path, ": ", func, "() failed with ", errstr, "\n", NULL);
tinyprint(2, path, ": ", func, ": ", errstr, "\n", NULL);
exit(1);
}
@ -108,7 +96,7 @@ bool IsSymlink(const char *path) {
}
wontreturn void PrintUsage(int rc, int fd) {
Print(fd, "usage: ", prog, USAGE, NULL);
tinyprint(fd, "usage: ", prog, USAGE, NULL);
exit(rc);
}
@ -161,7 +149,7 @@ char *Join(const char *a, const char *b) {
n = strlen(a);
m = strlen(b);
if (n + 1 + m + 1 > sizeof(dstfile)) {
Print(2, "error: mv: path too long\n", NULL);
tinyprint(2, "error: mv: path too long\n", NULL);
exit(1);
}
stpcpy(stpcpy(stpcpy(dstfile, a), "/"), b);
@ -192,7 +180,7 @@ void Mv(char *src, char *dst) {
strcpy(srcdir, "");
}
if (nftw(src, Visit, 20, 0) == -1) {
SysExit(src, "nftw");
SysDie(src, "nftw");
}
return;
}
@ -200,30 +188,31 @@ void Mv(char *src, char *dst) {
dst = Join(dst, basename(src));
}
if (!force && access(dst, W_OK) == -1 && errno != ENOENT) {
SysExit(dst, "access");
SysDie(dst, "access");
}
strcpy(mkbuf, dst);
if (makedirs((d = dirname(mkbuf)), 0755) == -1) {
SysExit(d, "makedirs");
SysDie(d, "makedirs");
}
if (IsSymlink(src)) {
if ((rc = readlink(src, linkbuf, sizeof(linkbuf) - 1)) == -1) {
SysExit(src, "readlink");
SysDie(src, "readlink");
}
linkbuf[rc] = 0;
if (symlink(linkbuf, dst)) {
SysExit(dst, "symlink");
SysDie(dst, "symlink");
}
} else {
if (rename(src, dst)) {
SysExit(src, "rename");
SysDie(src, "rename");
}
}
}
int main(int argc, char *argv[]) {
int i;
prog = argc > 0 ? argv[0] : "mv.com";
prog = argv[0];
if (!prog) prog = "mv";
GetOpts(argc, argv);
if (argc - optind < 2) PrintUsage(1, 2);
for (i = optind; i < argc - 1; ++i) {

View file

@ -1,79 +0,0 @@
/*-*- 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 2022 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/errno.h"
#include "libc/fmt/itoa.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/o.h"
#include "third_party/getopt/getopt.internal.h"
char buf[512];
static void Write(const char *s, ...) {
va_list va;
va_start(va, s);
do {
write(2, s, strlen(s));
} while ((s = va_arg(va, const char *)));
va_end(va);
}
wontreturn void SysExit(int rc, const char *call, const char *thing) {
int err;
char ibuf[12];
const char *estr;
err = errno;
FormatInt32(ibuf, err);
estr = _strerdoc(err);
if (!estr) estr = "EUNKNOWN";
Write(thing, ": ", call, "() failed: ", estr, " (", ibuf, ")\n", 0);
exit(rc);
}
int main(int argc, char *argv[]) {
int i, opt;
const char *outpath = "/dev/stdout";
while ((opt = getopt(argc, argv, "o:")) != -1) {
switch (opt) {
case 'o':
outpath = optarg;
break;
default:
return 1;
}
}
int out = open(outpath, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (out == -1) SysExit(2, "open", outpath);
for (i = optind; i < argc; ++i) {
int in = open(argv[i], O_RDONLY);
if (in == -1) SysExit(3, "open", argv[i]);
for (;;) {
ssize_t rc = read(in, buf, 512);
if (rc == -1) SysExit(3, "read", argv[i]);
if (!rc) break;
ssize_t rc2 = write(out, buf, rc);
if (rc2 != rc) SysExit(4, "write", outpath);
}
if (close(in) == -1) SysExit(5, "close", argv[i]);
}
if (close(out) == -1) SysExit(6, "close", outpath);
}

View file

@ -153,27 +153,15 @@ struct Relas {
} * p;
} prtu;
nullterminated() static void Print(int fd, const char *s, ...) {
va_list va;
char buf[2048];
va_start(va, s);
buf[0] = 0;
do {
strlcat(buf, s, sizeof(buf));
} while ((s = va_arg(va, const char *)));
write(fd, buf, strlen(buf));
va_end(va);
}
static wontreturn void Die(const char *path, const char *reason) {
Print(2, path, ": ", reason, "\n", NULL);
tinyprint(2, path, ": ", reason, "\n", NULL);
exit(1);
}
static wontreturn void SysExit(const char *path, const char *func) {
const char *errstr;
if (!(errstr = _strerrno(errno))) errstr = "EUNKNOWN";
Print(2, path, ": ", func, " failed with ", errstr, "\n", NULL);
tinyprint(2, path, ": ", func, " failed with ", errstr, "\n", NULL);
exit(1);
}
@ -321,7 +309,7 @@ static void WritePackage(struct Package *pkg) {
}
static wontreturn void PrintUsage(int fd, int exitcode) {
Print(fd, "\n\
tinyprint(fd, "\n\
NAME\n\
\n\
Cosmopolitan Monorepo Packager\n\
@ -329,7 +317,7 @@ NAME\n\
SYNOPSIS\n\
\n\
",
program_invocation_name, " [FLAGS] OBJECT...\n\
program_invocation_name, " [FLAGS] OBJECT...\n\
\n\
DESCRIPTION\n\
\n\
@ -345,7 +333,7 @@ FLAGS\n\
-d PATH package dependency path [repeatable]\n\
\n\
",
NULL);
NULL);
exit(exitcode);
}
@ -370,14 +358,15 @@ static void GetOpts(struct Package *pkg, struct Packages *deps, int argc,
}
}
if (pkg->path == -1) {
Print(2, "error: no packages passed to package.com\n", NULL);
tinyprint(2, "error: no packages passed to package.com\n", NULL);
exit(1);
}
if (optind == argc) {
Print(2,
"no objects passed to package.com; is your foo.mk $(FOO_OBJS) glob "
"broken?\n",
NULL);
tinyprint(
2,
"no objects passed to package.com; is your foo.mk $(FOO_OBJS) glob "
"broken?\n",
NULL);
exit(1);
}
getargs_init(&ga, argv + optind);
@ -495,7 +484,7 @@ static void LoadPriviligedRefsToUndefs(struct Package *pkg,
if (obj->syms[x].st_shndx) continue; // symbol is defined
if (ELF64_ST_BIND(obj->syms[x].st_info) != STB_WEAK &&
ELF64_ST_BIND(obj->syms[x].st_info) != STB_GLOBAL) {
Print(2, "warning: undefined symbol not global\n", NULL);
tinyprint(2, "warning: undefined symbol not global\n", NULL);
continue;
}
if (!(s = GetElfString(obj->elf, obj->size, obj->strs,
@ -602,13 +591,13 @@ static void CheckStrictDeps(struct Package *pkg, struct Packages *deps) {
undef = &pkg->undefs.p[i];
if (undef->bind_ == STB_WEAK) continue;
if (!FindSymbol(pkg->strings.p + undef->name, pkg, deps, NULL, NULL)) {
Print(2, pkg->strings.p + pkg->path, ": undefined symbol '",
pkg->strings.p + undef->name, "' (",
pkg->strings.p + pkg->objects.p[undef->object].path,
") not defined by direct dependencies:\n", NULL);
tinyprint(2, pkg->strings.p + pkg->path, ": undefined symbol '",
pkg->strings.p + undef->name, "' (",
pkg->strings.p + pkg->objects.p[undef->object].path,
") not defined by direct dependencies:\n", NULL);
for (j = 0; j < deps->i; ++j) {
dep = deps->p[j];
Print(2, "\t", dep->strings.p + dep->path, "\n", NULL);
tinyprint(2, "\t", dep->strings.p + dep->path, "\n", NULL);
}
exit(1);
}
@ -626,10 +615,11 @@ static void CheckYourPrivilege(struct Package *pkg, struct Packages *deps) {
name = prtu.p[i].symbol_name;
if (FindSymbol(name, pkg, deps, &dep, &sym) &&
dep->sections.p[sym->section].kind == kText) {
Print(2, prtu.p[i].object_path,
": privileged code referenced unprivileged symbol '", name,
"' in section '",
dep->strings.p + dep->sections.p[sym->section].name, "'\n", NULL);
tinyprint(2, prtu.p[i].object_path,
": privileged code referenced unprivileged symbol '", name,
"' in section '",
dep->strings.p + dep->sections.p[sym->section].name, "'\n",
NULL);
++f;
}
}

View file

@ -119,9 +119,7 @@ int main(int argc, char *argv[]) {
printf(U(argv[1]), argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
return 0;
default:
if (argc > 0) {
fprintf(stderr, "%s: %s format [arguments]\n", argv[0], argv[0]);
}
fprintf(stderr, "%s: %s format [arguments]\n", argv[0], argv[0]);
return 1;
}
}

View file

@ -1,990 +0,0 @@
/*-*- 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/struct/sigaction.h"
#include "libc/calls/struct/sigset.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/mem/gc.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.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/nr.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/sa.h"
#include "libc/sysv/consts/sig.h"
#include "libc/x/xasprintf.h"
#include "libc/x/xgetline.h"
#include "third_party/dlmalloc/dlmalloc.h"
#include "third_party/getopt/getopt.internal.h"
/**
* @fileoverview Pythonic System Call Trace
*
* This program invokes `strace` as a subprocess and turns its output
* into Python data structures. It is useful because strace output is
* this weird plaintext format that's so famously difficult to parse.
*
* For example, you can run this command:
*
* pstrace -o trace.pylog echo hello world
*
* After which you may parse the output with Python:
*
* for line in open('trace.pylog'):
* pid,time,elap,kind,x = eval(line)
* if kind == 1:
* name,ret,args = x
* print "%s%r -> %d" % (name, args, ret)
*
* This program traces the subset of system calls governing processes
* and files. To do that we must track file descriptor lifetimes too.
* We also track system calls that are problematic for build configs,
* such as sockets, since compiling code shouldn't need the Internet.
*
* @note this tool is linux only
* @note freebsd: truss PROC ARGS
* @note appleos: sudo dtruss PROC ARGS
* @note openbsd: ktrace PROC ARGS && kdump -f ktrace.out
* @note windows: https://github.com/rogerorr/NtTrace
*/
#define DEBUG "%ld: %s", lineno, line
#define READ128BE(S) ((uint128_t)READ64BE(S) << 64 | READ64BE((S) + 8))
#define APPEND(L) \
do { \
if (++L.n > L.c) { \
L.c = MAX(11, L.c); \
L.c += L.c >> 1; \
L.p = realloc(L.p, L.c * sizeof(*L.p)); \
} \
bzero(L.p + L.n - 1, sizeof(*L.p)); \
} while (0)
struct Trace {
struct Slices {
long n, c;
struct Slice {
int n, c;
char *p;
} * p;
} slices;
struct HashTable {
long i, n;
struct HashEntry {
long h;
long i;
} * p;
} sliceindex;
struct Strlists {
long n, c;
struct Strlist {
long n, c;
long *p; // slices.p[p[i]]
} * p;
} strlists;
struct Events {
long n, c;
struct Event {
enum EventKind {
EK_NONE,
EK_CALL,
EK_EXIT, // ret is kernel code
EK_SIGNAL, // ret is signal code
EK_KILLED, // ret is signal code
} kind;
unsigned char arity;
unsigned char syscall_;
bool is_interrupted;
int us;
int elap;
int pid;
long sec;
long ret;
long lineno;
struct Arg {
enum ArgKind {
AK_LONG, // x
AK_STR, // slices.p[x]
AK_STRLIST, // strlists.p[x]
AK_INTPAIR, // (x&0xffffffff, x>>32)
} kind;
long name;
long x;
} arg[6];
} * p;
} events;
};
static const struct Syscall {
char name[16];
} kSyscalls[] = {
{"accept"}, //
{"accept4"}, //
{"access"}, //
{"bind"}, //
{"chdir"}, //
{"chmod"}, //
{"chown"}, //
{"chroot"}, //
{"clone"}, //
{"close"}, //
{"connect"}, //
{"creat"}, //
{"dup"}, //
{"dup2"}, //
{"dup3"}, //
{"epoll_create"}, //
{"epoll_create1"}, //
{"eventfd"}, //
{"eventfd2"}, //
{"execve"}, //
{"execveat"}, //
{"faccessat"}, //
{"fchmodat"}, //
{"fchownat"}, //
{"fdatasync"}, //
{"fcntl"}, //
{"flock"}, //
{"fork"}, //
{"fsync"}, //
{"lchown"}, //
{"link"}, //
{"linkat"}, //
{"listen"}, //
{"memfd_create"}, //
{"mkdir"}, //
{"mkdirat"}, //
{"mknod"}, //
{"mknodat"}, //
{"open"}, //
{"openat"}, //
{"pipe"}, //
{"pipe2"}, //
{"readlink"}, //
{"readlinkat"}, //
{"rename"}, //
{"renameat"}, //
{"renameat2"}, //
{"rmdir"}, //
{"signalfd"}, //
{"signalfd4"}, //
{"socket"}, //
{"socketpair"}, //
{"statfs"}, //
{"symlink"}, //
{"symlinkat"}, //
{"sync"}, //
{"syncfs"}, //
{"timerfd_create"}, //
{"truncate"}, //
{"unlink"}, //
{"unlinkat"}, //
{"utimensat"}, //
{"vfork"}, //
};
static const struct Signal {
char name[8];
unsigned char number;
} kSignals[] = {
{"SIGABRT", 6}, //
{"SIGALRM", 14}, //
{"SIGBUS", 7}, //
{"SIGCHLD", 17}, //
{"SIGCONT", 18}, //
{"SIGFPE", 8}, //
{"SIGHUP", 1}, //
{"SIGILL", 4}, //
{"SIGINT", 2}, //
{"SIGIO", 29}, //
{"SIGIOT", 6}, //
{"SIGKILL", 9}, //
{"SIGPIPE", 13}, //
{"SIGPOLL", 29}, //
{"SIGPROF", 27}, //
{"SIGPWR", 30}, //
{"SIGQUIT", 3}, //
{"SIGSEGV", 11}, //
{"SIGSTOP", 19}, //
{"SIGSYS", 31}, //
{"SIGTERM", 15}, //
{"SIGTRAP", 5}, //
{"SIGTSTP", 20}, //
{"SIGTTIN", 21}, //
{"SIGTTOU", 22}, //
{"SIGURG", 23}, //
{"SIGUSR1", 10}, //
{"SIGUSR2", 12}, //
{"SIGWINCH", 28}, //
{"SIGXCPU", 24}, //
{"SIGXFSZ", 25}, //
};
static const struct Errno {
char name[16];
unsigned char number;
} kErrnos[] = {
{"E2BIG", 7}, //
{"EACCES", 13}, //
{"EADDRINUSE", 98}, //
{"EADDRNOTAVAIL", 99}, //
{"EADV", 68}, //
{"EAFNOSUPPORT", 97}, //
{"EAGAIN", 11}, //
{"EALREADY", 114}, //
{"EBADE", 52}, //
{"EBADF", 9}, //
{"EBADFD", 77}, //
{"EBADMSG", 74}, //
{"EBADR", 53}, //
{"EBADRQC", 56}, //
{"EBADSLT", 57}, //
{"EBFONT", 59}, //
{"EBUSY", 16}, //
{"ECANCELED", 125}, //
{"ECHILD", 10}, //
{"ECHRNG", 44}, //
{"ECOMM", 70}, //
{"ECONNABORTED", 103}, //
{"ECONNREFUSED", 111}, //
{"ECONNRESET", 104}, //
{"EDEADLK", 35}, //
{"EDESTADDRREQ", 89}, //
{"EDOM", 33}, //
{"EDOTDOT", 73}, //
{"EDQUOT", 122}, //
{"EEXIST", 17}, //
{"EFAULT", 14}, //
{"EFBIG", 27}, //
{"EHOSTDOWN", 112}, //
{"EHOSTUNREACH", 113}, //
{"EHWPOISON", 133}, //
{"EIDRM", 43}, //
{"EILSEQ", 84}, //
{"EINPROGRESS", 115}, //
{"EINTR", 4}, //
{"EINVAL", 22}, //
{"EIO", 5}, //
{"EISCONN", 106}, //
{"EISDIR", 21}, //
{"EISNAM", 120}, //
{"EKEYEXPIRED", 127}, //
{"EKEYREJECTED", 129}, //
{"EKEYREVOKED", 128}, //
{"EL2HLT", 51}, //
{"EL2NSYNC", 45}, //
{"EL3HLT", 46}, //
{"EL3RST", 47}, //
{"ELIBACC", 79}, //
{"ELIBBAD", 80}, //
{"ELIBEXEC", 83}, //
{"ELIBMAX", 82}, //
{"ELIBSCN", 81}, //
{"ELNRNG", 48}, //
{"ELOOP", 40}, //
{"EMEDIUMTYPE", 124}, //
{"EMFILE", 24}, //
{"EMLINK", 31}, //
{"EMSGSIZE", 90}, //
{"EMULTIHOP", 72}, //
{"ENAMETOOLONG", 36}, //
{"ENAVAIL", 119}, //
{"ENETDOWN", 100}, //
{"ENETRESET", 102}, //
{"ENETUNREACH", 101}, //
{"ENFILE", 23}, //
{"ENOANO", 55}, //
{"ENOBUFS", 105}, //
{"ENOCSI", 50}, //
{"ENODATA", 61}, //
{"ENODEV", 19}, //
{"ENOENT", 2}, //
{"ENOEXEC", 8}, //
{"ENOKEY", 126}, //
{"ENOLCK", 37}, //
{"ENOLINK", 67}, //
{"ENOMEDIUM", 123}, //
{"ENOMEM", 12}, //
{"ENOMSG", 42}, //
{"ENONET", 64}, //
{"ENOPKG", 65}, //
{"ENOPROTOOPT", 92}, //
{"ENOSPC", 28}, //
{"ENOSR", 63}, //
{"ENOSTR", 60}, //
{"ENOSYS", 38}, //
{"ENOTBLK", 15}, //
{"ENOTCONN", 107}, //
{"ENOTDIR", 20}, //
{"ENOTEMPTY", 39}, //
{"ENOTNAM", 118}, //
{"ENOTRECOVERABLE", 131}, //
{"ENOTSOCK", 88}, //
{"ENOTSUP", 95}, //
{"ENOTTY", 25}, //
{"ENOTUNIQ", 76}, //
{"ENXIO", 6}, //
{"EOPNOTSUPP", 95}, //
{"EOVERFLOW", 75}, //
{"EOWNERDEAD", 130}, //
{"EPERM", 1}, //
{"EPFNOSUPPORT", 96}, //
{"EPIPE", 32}, //
{"EPROTO", 71}, //
{"EPROTONOSUPPORT", 93}, //
{"EPROTOTYPE", 91}, //
{"ERANGE", 34}, //
{"EREMCHG", 78}, //
{"EREMOTE", 66}, //
{"EREMOTEIO", 121}, //
{"ERESTART", 85}, //
{"ERFKILL", 132}, //
{"EROFS", 30}, //
{"ESHUTDOWN", 108}, //
{"ESOCKTNOSUPPORT", 94}, //
{"ESPIPE", 29}, //
{"ESRCH", 3}, //
{"ESRMNT", 69}, //
{"ESTALE", 116}, //
{"ESTRPIPE", 86}, //
{"ETIME", 62}, //
{"ETIMEDOUT", 110}, //
{"ETOOMANYREFS", 109}, //
{"ETXTBSY", 26}, //
{"EUCLEAN", 117}, //
{"EUNATCH", 49}, //
{"EUSERS", 87}, //
{"EWOULDBLOCK", 11}, //
{"EXDEV", 18}, //
{"EXFULL", 54}, //
};
static char **strace_args;
static size_t strace_args_len;
static volatile bool interrupted;
static long Hash(const void *p, size_t n) {
unsigned h, i;
for (h = i = 0; i < n; i++) {
h += ((unsigned char *)p)[i];
h *= 0x9e3779b1;
}
return MAX(1, h);
}
static uint64_t MakeKey64(const char *p, size_t n) {
char k[8] = {0};
memcpy(k, p, n);
return READ64BE(k);
}
static uint128_t MakeKey128(const char *p, size_t n) {
char k[16] = {0};
memcpy(k, p, n);
return READ128BE(k);
}
static int GetSyscall(const char *name, size_t namelen) {
int m, l, r;
uint128_t x, y;
char *endofname;
if (namelen && namelen <= 16) {
x = MakeKey128(name, namelen);
l = 0;
r = ARRAYLEN(kSyscalls) - 1;
while (l <= r) {
m = (l + r) >> 1;
y = READ128BE(kSyscalls[m].name);
if (x < y) {
r = m - 1;
} else if (x > y) {
l = m + 1;
} else {
return m;
}
}
}
return -1;
}
static int GetErrno(const char *name, size_t namelen) {
int m, l, r;
uint128_t x, y;
char *endofname;
if (namelen && namelen <= 16) {
x = MakeKey128(name, namelen);
l = 0;
r = ARRAYLEN(kErrnos) - 1;
while (l <= r) {
m = (l + r) >> 1;
y = READ128BE(kErrnos[m].name);
if (x < y) {
r = m - 1;
} else if (x > y) {
l = m + 1;
} else {
return kErrnos[m].number;
}
}
}
return -1;
}
static int GetSignal(const char *name, size_t namelen) {
int m, l, r;
uint64_t x, y;
char *endofname;
if (namelen && namelen <= 8) {
x = MakeKey64(name, namelen);
l = 0;
r = ARRAYLEN(kSignals) - 1;
while (l <= r) {
m = (l + r) >> 1;
y = READ64BE(kSignals[m].name);
if (x < y) {
r = m - 1;
} else if (x > y) {
l = m + 1;
} else {
return kSignals[m].number;
}
}
}
return -1;
}
static struct Trace *NewTrace(void) {
return calloc(1, sizeof(struct Trace));
}
static void FreeTrace(struct Trace *t) {
long i;
if (t) {
for (i = 0; i < t->slices.n; ++i) {
free(t->slices.p[i].p);
}
free(t->slices.p);
free(t->sliceindex.p);
for (i = 0; i < t->strlists.n; ++i) {
free(t->strlists.p[i].p);
}
free(t->strlists.p);
free(t->events.p);
free(t);
}
}
static void AppendStrlists(struct Trace *t) {
APPEND(t->strlists);
}
static void AppendStrlist(struct Strlist *l) {
APPEND((*l));
}
static void AppendEvent(struct Trace *t) {
APPEND(t->events);
}
static void AppendSlices(struct Trace *t) {
APPEND(t->slices);
}
static void AppendSlice(struct Slice *s, int c) {
APPEND((*s));
s->p[s->n - 1] = c;
}
static long Intern(struct Trace *t, char *data, long size) {
struct HashEntry *p;
long i, j, k, n, m, h, n2;
h = Hash(data, size);
n = t->sliceindex.n;
i = 0;
if (n) {
k = 0;
do {
i = (h + k + ((k + 1) >> 1)) & (n - 1);
if (t->sliceindex.p[i].h == h &&
t->slices.p[t->sliceindex.p[i].i].n == size &&
!memcmp(t->slices.p[t->sliceindex.p[i].i].p, data, size)) {
free(data);
return t->sliceindex.p[i].i;
}
++k;
} while (t->sliceindex.p[i].h);
}
if (++t->sliceindex.i >= (n >> 1)) {
m = n ? n << 1 : 16;
p = calloc(m, sizeof(struct HashEntry));
for (j = 0; j < n; ++j) {
if (t->sliceindex.p[j].h) {
k = 0;
do {
i = (t->sliceindex.p[j].h + k + ((k + 1) >> 1)) & (m - 1);
++k;
} while (p[i].h);
p[i].h = t->sliceindex.p[j].h;
p[i].i = t->sliceindex.p[j].i;
}
}
k = 0;
do {
i = (h + k + ((k + 1) >> 1)) & (m - 1);
++k;
} while (p[i].h);
free(t->sliceindex.p);
t->sliceindex.p = p;
t->sliceindex.n = m;
}
AppendSlices(t);
t->slices.p[t->slices.n - 1].p = data;
t->slices.p[t->slices.n - 1].n = size;
t->sliceindex.p[i].i = t->slices.n - 1;
t->sliceindex.p[i].h = h;
return t->slices.n - 1;
}
static long ReadCharLiteral(struct Slice *buf, long c, char *p, long *i) {
if (c != '\\') return c;
switch ((c = p[(*i)++])) {
case 'a':
return '\a';
case 'b':
return '\b';
case 't':
return '\t';
case 'n':
return '\n';
case 'v':
return '\v';
case 'f':
return '\f';
case 'r':
return '\r';
case 'e':
return 033;
case 'x':
if (isxdigit(p[*i])) {
c = hextoint(p[(*i)++]);
if (isxdigit(p[*i])) {
c = c * 16 + hextoint(p[(*i)++]);
}
}
return c;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
c -= '0';
if ('0' <= p[*i] && p[*i] <= '7') {
c = c * 8 + (p[(*i)++] - '0');
if ('0' <= p[*i] && p[*i] <= '7') {
c = c * 8 + (p[(*i)++] - '0');
}
}
return c;
default:
return c;
}
}
static long GetDuration(long sec1, long us1, long sec2, long us2) {
long elap;
if ((elap = (sec2 - sec1) * 1000000)) {
return elap + 1000000 - us1 + us2;
} else {
return elap + us2 - us1;
}
}
static void Parse(struct Trace *t, const char *line, long lineno) {
char *p, *q;
struct Slice b;
long c, i, j, k, arg, pid, event, sec, us;
p = line;
pid = strtol(p, &p, 10);
while (*p == ' ') ++p;
sec = strtol(p, &p, 10);
CHECK_EQ('.', *p++, DEBUG);
us = strtol(p, &p, 10);
CHECK_EQ(' ', *p++, DEBUG);
if (_startswith(p, "<... ")) {
CHECK_NOTNULL((p = strchr(p, '>')));
++p;
for (event = t->events.n; event--;) {
if (t->events.p[event].pid == pid) {
CHECK(t->events.p[event].is_interrupted, DEBUG);
t->events.p[event].is_interrupted = false;
t->events.p[event].elap =
GetDuration(t->events.p[event].sec, t->events.p[event].us, sec, us);
break;
}
}
CHECK_GE(event, 0);
} else {
AppendEvent(t);
event = t->events.n - 1;
t->events.p[event].pid = pid;
t->events.p[event].sec = sec;
t->events.p[event].us = us;
t->events.p[event].lineno = lineno;
if (_startswith(p, "+++ exited with ")) {
p += strlen("+++ exited with ");
t->events.p[event].kind = EK_EXIT;
t->events.p[event].ret = atoi(p);
return;
} else if (_startswith(p, "+++ killed by ")) {
p += strlen("+++ killed by ");
CHECK((q = strchr(p, ' ')), DEBUG);
t->events.p[event].kind = EK_KILLED;
t->events.p[event].ret = GetSignal(p, q - p);
return;
} else if (_startswith(p, "--- ")) {
p += 4;
CHECK(isalpha(*p), DEBUG);
CHECK((q = strchr(p, ' ')), DEBUG);
t->events.p[event].kind = EK_SIGNAL;
t->events.p[event].ret = GetSignal(p, q - p);
return;
} else if (isalpha(*p) && (q = strchr(p, '('))) {
t->events.p[event].kind = EK_CALL;
CHECK_NE(-1, (t->events.p[event].syscall_ = GetSyscall(p, q - p)), DEBUG);
p = q + 1;
}
}
for (;;) {
if (*p == ',') ++p;
while (*p == ' ') ++p;
CHECK(*p, DEBUG);
if (_startswith(p, "<unfinished ...>")) {
t->events.p[event].is_interrupted = true;
break;
} else if (*p == ')') {
++p;
while (isspace(*p)) ++p;
CHECK_EQ('=', *p++, DEBUG);
while (isspace(*p)) ++p;
CHECK(isdigit(*p) || *p == '-', DEBUG);
t->events.p[event].ret = strtol(p, &p, 0);
if (t->events.p[event].ret == -1) {
while (isspace(*p)) ++p;
CHECK((q = strchr(p, ' ')), DEBUG);
if ((t->events.p[event].ret = GetErrno(p, q - p)) != -1) {
t->events.p[event].ret = -t->events.p[event].ret;
}
}
break;
}
CHECK_LT((arg = t->events.p[event].arity++), 6);
if (isalpha(*p) && !_startswith(p, "NULL")) {
bzero(&b, sizeof(b));
for (; isalpha(*p) || *p == '_'; ++p) {
AppendSlice(&b, *p);
}
t->events.p[event].arg[arg].name = Intern(t, b.p, b.n);
CHECK_EQ('=', *p++, DEBUG);
} else {
t->events.p[event].arg[arg].name = -1;
}
if (_startswith(p, "NULL")) {
p += 4;
t->events.p[event].arg[arg].kind = AK_LONG;
t->events.p[event].arg[arg].x = 0;
} else if (*p == '-' || isdigit(*p)) {
t->events.p[event].arg[arg].kind = AK_LONG;
for (;;) {
t->events.p[event].arg[arg].x |= strtol(p, &p, 0);
if (*p == '|') {
++p;
} else {
break;
}
}
} else if (*p == '{') {
CHECK_NOTNULL((p = strchr(p, '}')), DEBUG);
++p;
} else if (*p == '"') {
bzero(&b, sizeof(b));
for (j = 0; (c = p[++j]);) {
if (c == '"') {
p += j + 1;
break;
}
c = ReadCharLiteral(&b, c, p, &j);
AppendSlice(&b, c);
}
t->events.p[event].arg[arg].kind = AK_STR;
t->events.p[event].arg[arg].x = Intern(t, b.p, b.n);
} else if (*p == '[') {
++p;
if (isdigit(*p)) {
t->events.p[event].arg[arg].kind = AK_INTPAIR;
t->events.p[event].arg[arg].x = strtol(p, &p, 0) & 0xffffffff;
CHECK_EQ(',', *p++, DEBUG);
CHECK_EQ(' ', *p++, DEBUG);
t->events.p[event].arg[arg].x |= strtol(p, &p, 0) << 32;
CHECK_EQ(']', *p++, DEBUG);
} else {
AppendStrlists(t);
for (j = 0;; ++j) {
if (*p == ']') {
++p;
break;
}
if (*p == ',') ++p;
if (*p == ' ') ++p;
CHECK_EQ('"', *p, DEBUG);
bzero(&b, sizeof(b));
for (k = 0; (c = p[++k]);) {
if (c == '"') {
p += k + 1;
break;
}
c = ReadCharLiteral(&b, c, p, &k);
AppendSlice(&b, c);
}
AppendStrlist(&t->strlists.p[t->strlists.n - 1]);
t->strlists.p[t->strlists.n - 1]
.p[t->strlists.p[t->strlists.n - 1].n - 1] = Intern(t, b.p, b.n);
}
t->events.p[event].arg[arg].kind = AK_STRLIST;
t->events.p[event].arg[arg].x = t->strlists.n - 1;
}
} else {
CHECK(false, DEBUG);
}
}
}
static void PrintArg(FILE *f, struct Trace *t, long ev, long arg) {
long i, x;
x = t->events.p[ev].arg[arg].name;
if (x != -1) {
fprintf(f, "b%`'.*s:", t->slices.p[x].n, t->slices.p[x].p);
}
x = t->events.p[ev].arg[arg].x;
switch (t->events.p[ev].arg[arg].kind) {
case AK_LONG:
fprintf(f, "%ld", x);
break;
case AK_STR:
fprintf(f, "b%`'.*s", t->slices.p[x].n, t->slices.p[x].p);
break;
case AK_INTPAIR:
fprintf(f, "(%d,%d)", x >> 32, x);
break;
case AK_STRLIST:
fprintf(f, "(");
for (i = 0; i < t->strlists.p[x].n; ++i) {
fprintf(f, "b%`'.*s,", t->slices.p[t->strlists.p[x].p[i]].n,
t->slices.p[t->strlists.p[x].p[i]].p);
}
fprintf(f, ")");
break;
default:
abort();
}
}
static void PrintEvent(FILE *f, struct Trace *t, long ev) {
long arg;
fprintf(f, "(%d,%ld,%d,%d,", t->events.p[ev].pid,
t->events.p[ev].sec * 1000000 + t->events.p[ev].us,
t->events.p[ev].elap, t->events.p[ev].kind);
switch (t->events.p[ev].kind) {
case EK_EXIT:
case EK_SIGNAL:
case EK_KILLED:
fprintf(f, "%d", t->events.p[ev].ret);
break;
case EK_CALL:
CHECK_LT(t->events.p[ev].syscall_, ARRAYLEN(kSyscalls));
fprintf(f, "(b%`'s,%ld,", kSyscalls[t->events.p[ev].syscall_].name,
t->events.p[ev].ret);
fprintf(f, "%c",
t->events.p[ev].arity && t->events.p[ev].arg[0].name != -1 ? '{'
: '(');
for (arg = 0; arg < t->events.p[ev].arity; ++arg) {
PrintArg(f, t, ev, arg);
fprintf(f, ",");
}
fprintf(f, "%c)",
t->events.p[ev].arity && t->events.p[ev].arg[0].name != -1 ? '}'
: ')');
break;
default:
break;
}
fprintf(f, ")");
}
static void AppendArg(char *arg) {
strace_args = realloc(strace_args, ++strace_args_len * sizeof(*strace_args));
strace_args[strace_args_len - 1] = arg;
}
static wontreturn void PrintUsage(FILE *f, int rc) {
fprintf(f, "Usage: %s [-o OUT] PROG [ARGS...]\n", program_invocation_name);
exit(rc);
}
int main(int argc, char *argv[]) {
int i;
int ws;
int opt;
int pid;
long ev;
FILE *fin;
FILE *fout;
char *line;
long lineno;
char *strace;
int pipefds[2];
struct Trace *t;
sigset_t block, mask;
struct sigaction ignore, saveint, savequit;
/*
* parse prefix arguments
*/
fout = stderr;
while ((opt = getopt(argc, argv, "?ho:")) != -1) {
switch (opt) {
case 'o':
fout = fopen(optarg, "w");
break;
case 'h':
case '?':
PrintUsage(stdout, EXIT_SUCCESS);
default:
PrintUsage(stderr, EX_USAGE);
}
}
if (optind == argc) {
PrintUsage(stderr, EX_USAGE);
}
/*
* resolve full paths of dependencies
*/
if ((strace = commandvenv("STRACE", "strace"))) {
strace = strdup(strace);
} else {
fprintf(stderr, "error: please install strace\n");
exit(1);
}
/*
* create strace argument list
*/
AppendArg("strace");
AppendArg("-q"); // don't log attach/detach noise
AppendArg("-v"); // don't abbreviate arrays
AppendArg("-f"); // follow subprocesses
AppendArg("-ttt"); // print unixseconds.micros
AppendArg("-X"); // print numbers instead of symbols
AppendArg("raw"); // e.g. 2 vs. O_RDWR
AppendArg("-s"); // don't abbreviate data
AppendArg("805306368"); // strace won't let us go higher
AppendArg("-e"); // system calls that matter
AppendArg(
"open,close,access,pipe,dup,dup2,socket,connect,accept,bind,listen,"
"socketpair,fork,vfork,execve,clone,flock,fsync,fdatasync,truncate,chdir,"
"rename,mkdir,rmdir,creat,link,unlink,symlink,readlink,chmod,chown,fcntl,"
"lchown,mknod,mknodat,statfs,chroot,sync,epoll_create,openat,mkdirat,"
"fchownat,unlinkat,renameat,linkat,symlinkat,readlinkat,fchmodat,fchdir,"
"faccessat,utimensat,accept4,dup3,pipe2,epoll_create1,signalfd,signalfd4,"
"eventfd,eventfd2,timerfd_create,syncfs,renameat2,memfd_create,execveat");
CHECK_NE(-1, pipe(pipefds));
AppendArg("-o");
AppendArg(xasprintf("/dev/fd/%d", pipefds[1]));
for (i = optind; i < argc; ++i) {
AppendArg(argv[i]);
}
AppendArg(NULL);
/*
* spawn strace
*/
ignore.sa_flags = 0;
ignore.sa_handler = SIG_IGN;
sigemptyset(&ignore.sa_mask);
sigaction(SIGINT, &ignore, &saveint);
sigaction(SIGQUIT, &ignore, &savequit);
sigfillset(&block);
sigprocmask(SIG_BLOCK, &block, &mask);
CHECK_NE(-1, (pid = vfork()));
if (!pid) {
close(pipefds[0]);
sigaction(SIGINT, &saveint, NULL);
sigaction(SIGQUIT, &savequit, NULL);
sigprocmask(SIG_SETMASK, &mask, NULL);
execv(strace, strace_args);
_exit(127);
}
close(pipefds[1]);
sigaddset(&mask, SIGCHLD);
sigprocmask(SIG_SETMASK, &mask, NULL);
/*
* read output of strace until eof
*/
fin = fdopen(pipefds[0], "r");
t = NewTrace();
for (ev = 0, lineno = 1; !interrupted && (line = xgetline(fin)); ++lineno) {
_chomp(line);
Parse(t, line, lineno);
free(line);
for (; ev < t->events.n && !t->events.p[ev].is_interrupted; ++ev) {
PrintEvent(fout, t, ev);
fprintf(fout, "\n");
}
}
FreeTrace(t);
CHECK_NE(-1, fclose(fout));
/*
* wait for strace to exit
*/
while (waitpid(pid, &ws, 0) == -1) {
CHECK_EQ(EINTR, errno);
}
CHECK_NE(-1, fclose(fin));
/*
* propagate exit
*/
if (WIFEXITED(ws)) {
return WEXITSTATUS(ws);
} else {
return 128 + WTERMSIG(ws);
}
}

View file

@ -17,21 +17,27 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
/**
* @fileoverview Tool for printing current directory.
*/
char path[PATH_MAX];
int main(int argc, char *argv[]) {
char *p;
if ((p = getcwd(path, sizeof(path)))) {
fputs(p, stdout);
fputc('\n', stdout);
return 0;
} else {
return 1;
char path[PATH_MAX + 2];
if (!getcwd(path, PATH_MAX)) {
perror(argv[0]);
exit(1);
}
strcat(path, "\n");
if (write(1, path, strlen(path)) == -1) {
perror("write");
exit(1);
}
return 0;
}

View file

@ -1,134 +0,0 @@
/*-*- 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
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/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/stat.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/log/check.h"
#include "libc/mem/alg.h"
#include "libc/mem/gc.internal.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/dt.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/x/x.h"
/**
* @fileoverview Pretty fast substring refactor tool.
*/
static const char kBefore[] = "\
Copyright 2020 Justine Alexandra Roberts Tunney \n\
\n\
This program is free software; you can redistribute it and/or modify \n\
it under the terms of the GNU General Public License as published by \n\
the Free Software Foundation; version 2 of the License. \n\
\n\
This program is distributed in the hope that it will be useful, but \n\
WITHOUT ANY WARRANTY; without even the implied warranty of \n\
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU \n\
General Public License for more details. \n\
\n\
You should have received a copy of the GNU General Public License \n\
along with this program; if not, write to the Free Software \n\
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA \n\
02110-1301 USA \n\
";
const char kAfter[] = "\
Copyright 2020 Justine Alexandra Roberts Tunney \n\
\n\
Permission to use, copy, modify, and/or distribute this software for \n\
any purpose with or without fee is hereby granted, provided that the \n\
above copyright notice and this permission notice appear in all copies. \n\
\n\
THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL │\n\
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED \n\
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE \n\
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL \n\
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR \n\
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER \n\
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR \n\
PERFORMANCE OF THIS SOFTWARE. \n\
";
#if 0
static const char kBefore[] = "\
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│";
const char kAfter[] = "\
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│";
#endif
void RefactorFile(const char *path) {
int fd;
struct stat st;
size_t len, partlen, len1, len2;
char *mem, *spot = NULL, *part1, *part2;
CHECK_NE(-1, (fd = open(path, O_RDONLY)));
CHECK_NE(-1, fstat(fd, &st));
len2 = 0;
if ((len = st.st_size)) {
CHECK_NE(MAP_FAILED,
(mem = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0)));
partlen = sizeof(kBefore) - 1;
if ((spot = memmem(mem, len, kBefore, partlen))) {
part1 = gc(xmalloc((len1 = spot - mem)));
part2 = gc(xmalloc((len2 = len - partlen - (spot - mem))));
memcpy(part1, mem, len1);
memcpy(part2, spot + partlen, len2);
}
CHECK_NE(-1, munmap(mem, len));
}
CHECK_NE(-1, close(fd));
if (spot) {
fprintf(stderr, "found! %s\n", path);
CHECK_NE(-1, (fd = open(path, O_RDWR | O_TRUNC)));
CHECK_EQ(len1, write(fd, part1, len1));
CHECK_EQ(sizeof(kAfter) - 1, write(fd, kAfter, sizeof(kAfter) - 1));
CHECK_EQ(len2, write(fd, part2, len2));
CHECK_NE(-1, close(fd));
}
}
void RefactorDir(const char *dpath) {
DIR *dir;
struct dirent *ent;
char *path = gc(xmalloc(4096));
CHECK_NOTNULL(dir = opendir(firstnonnull(dpath, ".")));
while ((ent = readdir(dir))) {
if (_startswith(ent->d_name, ".")) continue;
if (strcmp(ent->d_name, "o") == 0) continue;
snprintf(path, 4096, "%s%s%s", dpath ? dpath : "", dpath ? "/" : "",
ent->d_name);
if (isdirectory(path)) {
RefactorDir(path);
} else if (isregularfile(path)) {
RefactorFile(path);
}
}
CHECK_NE(-1, closedir(dir));
}
int main(int argc, char *argv[]) {
RefactorDir(NULL);
return 0;
}

View file

@ -1,251 +0,0 @@
/*-*- 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
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/dce.h"
#include "libc/errno.h"
#include "libc/fmt/fmt.h"
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.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/errfuns.h"
#include "third_party/getopt/getopt.internal.h"
#define USAGE1 \
"NAME\n\
\n\
rle - Run Length Encoder\n\
\n\
SYNOPSIS\n\
\n\
"
#define USAGE2 \
" [FLAGS] [FILE...]\n\
\n\
DESCRIPTION\n\
\n\
This is a primitive compression algorithm. Its advantage is that\n\
the concomitant rldecode() library is seventeen bytes, and works\n\
on IA-16, IA-32, and NexGen32e without needing to be recompiled.\n\
\n\
This CLI is consistent with gzip, bzip2, lzma, etc.\n\
\n\
FLAGS\n\
\n\
-1 .. -9 ignored\n\
-a ignored\n\
-c send to stdout\n\
-d decompress\n\
-f ignored\n\
-t test integrity\n\
-S SUFFIX overrides .rle extension\n\
-h shows this information\n"
FILE *fin_, *fout_;
bool decompress_, test_;
const char *suffix_, *hint_;
void StartErrorMessage(void) {
fputs("error: ", stderr);
fputs(hint_, stderr);
fputs(": ", stderr);
}
void PrintIoErrorMessage(void) {
int err;
err = errno;
StartErrorMessage();
fputs(strerror(err), stderr);
fputc('\n', stderr);
}
void PrintUsage(int rc, FILE *f) {
fputs(USAGE1, f);
fputs(program_invocation_name, f);
fputs(USAGE2, f);
exit(rc);
}
void GetOpts(int argc, char *argv[]) {
int opt;
fin_ = stdin;
suffix_ = ".rle";
while ((opt = getopt(argc, argv, "123456789S:acdfho:t")) != -1) {
switch (opt) {
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case 'a':
case 'f':
break;
case 'c':
fout_ = stdout;
break;
case 'd':
decompress_ = true;
break;
case 't':
test_ = true;
break;
case 'o':
fclose(fout_);
if (!(fout_ = fopen((hint_ = optarg), "w"))) {
PrintIoErrorMessage();
exit(1);
}
break;
case 'S':
suffix_ = optarg;
break;
case 'h':
case '?':
PrintUsage(EXIT_SUCCESS, stdout);
default:
PrintUsage(EX_USAGE, stderr);
}
}
}
int RunLengthEncode1(void) {
int byte1, byte2, runlength;
byte2 = -1;
runlength = 0;
if ((byte1 = fgetc(fin_)) == -1) return -1;
do {
while (++runlength < 255) {
if ((byte2 = fgetc(fin_)) != byte1) break;
}
if (fputc(runlength, fout_) == -1 || fputc(byte1, fout_) == -1) {
return -1;
}
runlength = 0;
} while ((byte1 = byte2) != -1);
return feof(fin_) ? 0 : -1;
}
int RunLengthEncode2(void) {
return fputc(0, fout_) | fputc(0, fout_);
}
int EmitRun(unsigned char count, unsigned char byte) {
do {
if (fputc(byte, fout_) == -1) return -1;
} while (--count);
return 0;
}
int RunLengthDecode(void) {
int byte1, byte2;
if ((byte1 = fgetc(fin_)) == -1) return einval();
if ((byte2 = fgetc(fin_)) == -1) return einval();
while (byte1) {
if (!test_ && EmitRun(byte1, byte2) == -1) return -1;
if ((byte1 = fgetc(fin_)) == -1) break;
if ((byte2 = fgetc(fin_)) == -1) return einval();
}
if (byte1 != 0 || byte2 != 0) return einval();
fgetc(fin_);
return feof(fin_) ? 0 : -1;
}
int RunLengthCode(void) {
if (test_ || decompress_) {
return RunLengthDecode();
} else {
return RunLengthEncode1();
}
}
int Run(char **paths, size_t count) {
int rc;
char *p;
size_t i, suffixlen;
const char pathbuf[PATH_MAX];
if (!count) {
hint_ = "/dev/stdin";
if (!fout_) fout_ = stdout;
rc = RunLengthCode();
rc |= fclose(fin_);
fin_ = 0;
} else {
rc = fclose(fin_);
fin_ = 0;
for (i = 0; i < count && rc != -1; ++i) {
rc = -1;
if ((fin_ = fopen((hint_ = paths[i]), "r"))) {
if (test_ || fout_) {
rc = RunLengthCode();
} else {
suffixlen = strlen(suffix_);
if (!IsTrustworthy() &&
strlen(paths[i]) + suffixlen >= ARRAYLEN(pathbuf)) {
return eoverflow();
}
p = stpcpy(pathbuf, paths[i]);
if (!decompress_) {
strcpy(p, suffix_);
} else if (p - pathbuf > suffixlen &&
memcmp(p - suffixlen, suffix_, suffixlen) == 0) {
p[-suffixlen] = '\0';
} else {
return enotsup();
}
if ((fout_ = fopen((hint_ = pathbuf), "w"))) {
rc = RunLengthCode();
if (rc != -1 && !decompress_) {
rc = RunLengthEncode2();
}
if ((rc |= fclose(fout_)) != -1) {
unlink(paths[i]);
}
fout_ = 0;
}
}
rc |= fclose(fin_);
fin_ = 0;
}
}
}
if (rc != -1 && fout_) {
rc = RunLengthEncode2();
rc |= fclose(fout_);
fout_ = 0;
}
return rc;
}
int main(int argc, char *argv[]) {
GetOpts(argc, argv);
if (Run(argv + optind, argc - optind) != -1) {
return EXIT_SUCCESS;
} else {
PrintIoErrorMessage();
return EXIT_FAILURE;
}
}

View file

@ -22,8 +22,6 @@
#include "libc/runtime/runtime.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/ok.h"
#include "third_party/getopt/getopt.internal.h"
@ -36,63 +34,53 @@ SYNOPSIS\n\
\n\
FLAGS\n\
\n\
-?\n\
-h help\n\
-f force\n\
\n"
bool force;
const char *prog;
static bool force;
static const char *prog;
wontreturn void PrintUsage(int rc, FILE *f) {
fputs("usage: ", f);
fputs(prog, f);
fputs(USAGE, f);
static wontreturn void PrintUsage(int rc, int fd) {
tinyprint(fd, "USAGE\n\n ", prog, USAGE, NULL);
exit(rc);
}
void GetOpts(int argc, char *argv[]) {
static void GetOpts(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "?hf")) != -1) {
while ((opt = getopt(argc, argv, "hf")) != -1) {
switch (opt) {
case 'f':
force = true;
break;
case 'h':
case '?':
PrintUsage(EXIT_SUCCESS, stdout);
PrintUsage(0, 1);
default:
PrintUsage(EX_USAGE, stderr);
PrintUsage(1, 2);
}
}
}
void Remove(const char *path) {
const char *s;
if (!force && access(path, W_OK) == -1) goto OnFail;
if (unlink(path) == -1) goto OnFail;
return;
OnFail:
if (force && errno == ENOENT) return;
s = _strerdoc(errno);
fputs(prog, stderr);
fputs(": cannot remove '", stderr);
fputs(path, stderr);
fputs("': ", stderr);
fputs(s, stderr);
fputs("\n", stderr);
exit(1);
static void Remove(const char *path) {
if (!force && access(path, W_OK) == -1) {
perror(path);
exit(1);
}
if (unlink(path) == -1) {
if (force && errno == ENOENT) return;
perror(path);
exit(1);
}
}
int main(int argc, char *argv[]) {
int i;
prog = argc > 0 ? argv[0] : "rm.com";
prog = argv[0];
if (!prog) prog = "rm";
if (argc < 2) {
fputs(prog, stderr);
fputs(": missing operand\n"
"Try 'rm -h' for more information.\n",
stderr);
tinyprint(2, prog, ": missing operand\n", NULL);
exit(1);
}

View file

@ -28,17 +28,15 @@
#include "third_party/getopt/getopt.internal.h"
#include "third_party/mbedtls/sha256.h"
#define PROG "sha256sum"
#define USAGE \
"\
Usage: " PROG " [-?hbctw] [PATH...]\n\
"[-?hbctw] [PATH...]\n\
-h help\n\
-c check mode\n\
-b binary mode\n\
-t textual mode\n\
-w warning mode\n\
\n\
cosmopolitan " PROG " v1.0\n\
cosmopolitan sha256sum v1.1\n\
copyright 2022 justine alexandra roberts tunney\n\
notice licenses are embedded in the binary\n\
https://twitter.com/justinetunney\n\
@ -56,11 +54,17 @@ static bool g_warn;
static char g_mode;
static bool g_check;
static int g_mismatches;
static const char *prog;
static wontreturn void PrintUsage(int rc, int fd) {
tinyprint(fd, "Usage: ", prog, USAGE, NULL);
exit(rc);
}
static void GetOpts(int argc, char *argv[]) {
int opt;
g_mode = ' ';
while ((opt = getopt(argc, argv, "?hbctw")) != -1) {
while ((opt = getopt(argc, argv, "hbctw")) != -1) {
switch (opt) {
case 'w':
g_warn = true;
@ -75,28 +79,13 @@ static void GetOpts(int argc, char *argv[]) {
g_mode = '*';
break;
case 'h':
case '?':
write(1, USAGE, sizeof(USAGE) - 1);
exit(0);
PrintUsage(0, 1);
default:
write(2, USAGE, sizeof(USAGE) - 1);
exit(64);
PrintUsage(1, 2);
}
}
}
static ssize_t Write(int fd, const char *s, ...) {
va_list va;
char buf[512];
buf[0] = 0;
va_start(va, s);
do {
strlcat(buf, s, sizeof(buf));
} while ((s = va_arg(va, const char *)));
va_end(va);
return write(fd, buf, strlen(buf));
}
static bool IsModeCharacter(char c) {
switch (c) {
case ' ':
@ -117,7 +106,7 @@ static bool IsSupportedPath(const char *path) {
case '\r':
case '\n':
case '\\':
Write(2, PROG, ": ", path, ": unsupported path\n", NULL);
tinyprint(2, prog, ": ", path, ": unsupported path\n", NULL);
return false;
default:
break;
@ -135,7 +124,7 @@ static bool GetDigest(const char *path, FILE *f, unsigned char digest[32]) {
_unassert(!mbedtls_sha256_update_ret(&ctx, buf, got));
}
if (ferror(f)) {
Write(2, PROG, ": ", path, ": ", _strerdoc(errno), "\n", NULL);
tinyprint(2, prog, ": ", path, ": ", strerror(errno), "\n", NULL);
return false;
}
_unassert(!mbedtls_sha256_finish_ret(&ctx, digest));
@ -150,7 +139,7 @@ static bool ProduceDigest(const char *path, FILE *f) {
if (!IsSupportedPath(path)) return false;
if (!GetDigest(path, f, digest)) return false;
hexpcpy(hexdigest, digest, 32);
Write(1, hexdigest, " ", mode, path, "\n", NULL);
tinyprint(1, hexdigest, " ", mode, path, "\n", NULL);
return true;
}
@ -182,13 +171,13 @@ static bool CheckDigests(const char *path, FILE *f) {
++g_mismatches;
k = false;
}
Write(1, path2, ": ", status, "\n", NULL);
tinyprint(1, path2, ": ", status, "\n", NULL);
} else {
k = false;
}
fclose(f2);
} else {
Write(2, PROG, ": ", path2, ": ", _strerdoc(errno), "\n", NULL);
tinyprint(2, prog, ": ", path2, ": ", strerror(errno), "\n", NULL);
k = false;
}
continue;
@ -196,12 +185,12 @@ static bool CheckDigests(const char *path, FILE *f) {
if (g_warn) {
char linestr[12];
FormatInt32(linestr, line + 1);
Write(2, PROG, ": ", path, ":", linestr, ": ",
"improperly formatted checksum line", "\n", NULL);
tinyprint(2, prog, ": ", path, ":", linestr, ": ",
"improperly formatted checksum line", "\n", NULL);
}
}
if (ferror(f)) {
Write(2, PROG, ": ", path, ": ", _strerdoc(errno), "\n", NULL);
tinyprint(2, prog, ": ", path, ": ", strerror(errno), "\n", NULL);
k = false;
}
return k;
@ -219,6 +208,8 @@ int main(int argc, char *argv[]) {
int i;
FILE *f;
bool k = true;
prog = argv[0];
if (!prog) prog = "sha256sum";
GetOpts(argc, argv);
if (optind == argc) {
f = stdin;
@ -229,7 +220,7 @@ int main(int argc, char *argv[]) {
k &= Process(argv[i], f);
fclose(f);
} else {
Write(2, PROG, ": ", argv[i], ": ", _strerdoc(errno), "\n", NULL);
tinyprint(2, prog, ": ", argv[i], ": ", strerror(errno), "\n", NULL);
k = false;
}
}
@ -237,8 +228,8 @@ int main(int argc, char *argv[]) {
if (g_mismatches) {
char ibuf[12];
FormatInt32(ibuf, g_mismatches);
Write(2, PROG, ": WARNING: ", ibuf, " computed checksum did NOT match\n",
NULL);
tinyprint(2, prog, ": WARNING: ", ibuf,
" computed checksum did NOT match\n", NULL);
}
return !k;
}

View file

@ -17,31 +17,31 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
/**
* @fileoverview Command for updating timestamps on files.
* @fileoverview file timestamp update command
*/
int main(int argc, char *argv[]) {
int i;
const char *s, *prog;
prog = argc > 0 ? argv[0] : "touch.com";
const char *prog;
prog = argv[0];
if (!prog) prog = "touch";
if (argc < 2) {
tinyprint(2, prog, ": missing operand\n", NULL);
exit(1);
}
for (i = 1; i < argc; ++i) {
if (touch(argv[i], 0666) == -1) {
s = _strerdoc(errno);
fputs(prog, stderr);
fputs(": cannot touch '", stderr);
fputs(argv[i], stderr);
fputs("': ", stderr);
fputs(s, stderr);
fputs("\n", stderr);
perror(argv[i]);
exit(1);
}
}
return 0;
}

View file

@ -74,7 +74,8 @@ int Visit(const char *fpath, const struct stat *sb, int tflag,
int main(int argc, char *argv[]) {
if (!IsLinux()) return 0;
prog = argc > 0 ? argv[0] : "unbundle.com";
prog = argv[0];
if (!prog) prog = "unbundle";
if (IsDirectory("o/third_party/gcc")) return 0;
makedirs("o/third_party", 0755);
FormatInt32(stpcpy(tmpdir, "o/third_party/gcc."), getpid());

View file

@ -1,330 +0,0 @@
/*-*- 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 2022 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/assert.h"
#include "libc/calls/calls.h"
#include "libc/fmt/conv.h"
#include "libc/log/check.h"
#include "libc/math.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/str/tab.internal.h"
#include "libc/x/xasprintf.h"
/**
* @fileoverview Tool for generating rldecode'd character sets, e.g.
*
* # generate http token table
* o//tool/build/xlat.com -TiC ' ()<>@,;:\"/[]?={}' -i
*/
int dig;
int xlat[256];
bool identity;
const char *symbol;
static int Bing(int c) {
if (!c) return L'';
if (c == ' ') return L'';
if (c == '$') return L'§';
if (c == '\\') return L'';
return kCp437[c & 255];
}
static void Fill(int f(int)) {
int i;
for (i = 0; i < 256; ++i) {
if (f(i)) {
xlat[i] = identity ? i : 1;
}
}
}
static void Invert(void) {
int i;
for (i = 0; i < 256; ++i) {
xlat[i] = !xlat[i];
}
}
static void Negate(void) {
int i;
for (i = 0; i < 256; ++i) {
xlat[i] = ~xlat[i] & 255;
}
}
static void Negative(void) {
int i;
for (i = 0; i < 256; ++i) {
xlat[i] = -xlat[i] & 255;
}
}
static bool ArgNeedsShellQuotes(const char *s) {
if (*s) {
for (;;) {
switch (*s++ & 255) {
case 0:
return false;
case '-':
case '.':
case '/':
case '_':
case '=':
case ':':
case '0' ... '9':
case 'A' ... 'Z':
case 'a' ... 'z':
break;
default:
return true;
}
}
} else {
return true;
}
}
static char *AddShellQuotes(const char *s) {
char *p, *q;
size_t i, j, n;
n = strlen(s);
p = malloc(1 + n * 5 + 1 + 1);
j = 0;
p[j++] = '\'';
for (i = 0; i < n; ++i) {
if (s[i] != '\'') {
p[j++] = s[i];
} else {
p[j + 0] = '\'';
p[j + 1] = '"';
p[j + 2] = '\'';
p[j + 3] = '"';
p[j + 4] = '\'';
j += 5;
}
}
p[j++] = '\'';
p[j] = 0;
if ((q = realloc(p, j + 1))) p = q;
return p;
}
static const char *GetArg(char *argv[], int i, int *k) {
if (argv[*k][i + 1]) {
return argv[*k] + i + 1;
} else {
return argv[++*k];
}
}
int main(int argc, char *argv[]) {
const char *arg;
int i, j, k, opt;
dig = 1;
symbol = "kXlatTab";
for (k = 1; k < argc; ++k) {
if (argv[k][0] != '-') {
for (i = 0; argv[k][i]; ++i) {
/* xlat[argv[k][i] & 255] = identity ? i : dig; */
xlat[argv[k][i] & 255] = identity ? (argv[k][i] & 255) : dig;
}
} else {
i = 0;
moar:
++i;
if ((opt = argv[k][i])) {
switch (opt) {
case 's':
symbol = GetArg(argv, i, &k);
break;
case 'x':
dig = atoi(GetArg(argv, i, &k)) & 255;
break;
case 'i':
Invert();
goto moar;
case 'I':
identity = !identity;
goto moar;
case 'n':
Negative();
goto moar;
case 'N':
Negate();
goto moar;
case 'T':
Fill(isascii);
goto moar;
case 'C':
Fill(iscntrl);
goto moar;
case 'A':
Fill(isalpha);
goto moar;
case 'B':
Fill(isblank);
goto moar;
case 'G':
Fill(isgraph);
goto moar;
case 'P':
Fill(ispunct);
goto moar;
case 'D':
Fill(isdigit);
goto moar;
case 'U':
Fill(isupper);
goto moar;
case 'L':
Fill(islower);
goto moar;
default:
fprintf(stderr, "error: unrecognized option: %c\n", opt);
return 1;
}
}
}
}
////////////////////////////////////////////////////////////
printf("#include \"libc/macros.internal.h\"\n");
printf("\n");
printf("//\tgenerated by:\n");
printf("//\t");
for (i = 0; i < argc; ++i) {
if (i) printf(" ");
printf("%s", !ArgNeedsShellQuotes(argv[i]) ? argv[i]
: _gc(AddShellQuotes(argv[i])));
}
printf("\n");
////////////////////////////////////////////////////////////
printf("//\n");
printf("//\t present absent\n");
printf("//\t ──────────────── ────────────────\n");
for (i = 0; i < 16; ++i) {
char16_t absent[16];
char16_t present[16];
for (j = 0; j < 16; ++j) {
if (xlat[i * 16 + j]) {
absent[j] = L' ';
present[j] = Bing(i * 16 + j);
} else {
absent[j] = Bing(i * 16 + j);
present[j] = L' ';
}
}
printf("//\t %.16hs %.16hs 0x%02x\n", present, absent, i * 16);
}
////////////////////////////////////////////////////////////
printf("//\n");
printf("//\tconst char %s[256] = {\n//\t", symbol);
for (i = 0; i < 16; ++i) {
printf(" ");
for (j = 0; j < 16; ++j) {
printf("%2d,", (char)xlat[i * 16 + j]);
}
printf(" // 0x%02x\n//\t", i * 16);
}
printf("};\n");
printf("\n");
////////////////////////////////////////////////////////////
printf("\t.initbss 300,_init_%s\n", symbol);
printf("%s:\n", symbol);
printf("\t.zero\t256\n");
printf("\t.endobj\t%s,globl\n", symbol);
printf("\t.previous\n");
printf("\n");
////////////////////////////////////////////////////////////
printf("\t.initro 300,_init_%s\n", symbol);
printf("%s.rom:\n", symbol);
int thebloat = 0;
int thetally = 0;
int thecount = 0;
int runstart = 0;
int runchar = -1;
int runcount = 0;
for (i = 0;; ++i) {
if (i < 256 && xlat[i] == runchar) {
++runcount;
} else {
if (runcount) {
printf("\t.byte\t%-24s# %02x-%02x %hc-%hc\n",
_gc(xasprintf("%3d,%d", runcount, runchar)), runstart,
runstart + runcount - 1, Bing(runstart),
Bing(runstart + runcount - 1));
thetally += 2;
thecount += runcount;
}
if (i < 256) {
runcount = 1;
runchar = xlat[i];
runstart = i;
}
}
if (i == 256) {
break;
}
}
CHECK_EQ(256, thecount);
printf("\t.byte\t%-24s# terminator\n", "0,0");
thetally += 2;
thebloat = thetally;
for (i = 0; (thetally + i) % 8; i += 2) {
printf("\t.byte\t%-24s# padding\n", "0,0");
thebloat += 2;
}
printf("\t.endobj\t%s.rom,globl\n", symbol);
printf("\n");
////////////////////////////////////////////////////////////
printf("\t.init.start 300,_init_%s\n", symbol);
printf("\tcall\trldecode\n");
thebloat += 5;
int padding = 8 - thetally % 8;
if (padding < 8) {
if (padding >= 4) {
thebloat += 1;
printf("\tlodsl\n");
padding -= 4;
}
if (padding >= 2) {
thebloat += 2;
printf("\tlodsw\n");
}
}
printf("\t.init.end 300,_init_%s\n", symbol);
////////////////////////////////////////////////////////////
printf("\n");
printf("//\t%d bytes total (%d%% original size)\n", thebloat,
(int)round((double)thebloat / 256 * 100));
}

View file

@ -38,32 +38,20 @@ static const char *inpath;
static const char *outpath;
static unsigned char *inmap;
nullterminated() static void Print(int fd, const char *s, ...) {
va_list va;
char buf[2048];
va_start(va, s);
buf[0] = 0;
do {
strlcat(buf, s, sizeof(buf));
} while ((s = va_arg(va, const char *)));
write(fd, buf, strlen(buf));
va_end(va);
}
static wontreturn void Die(const char *path, const char *reason) {
Print(2, path, ": ", reason, "\n", NULL);
tinyprint(2, path, ": ", reason, "\n", NULL);
exit(1);
}
static wontreturn void SysExit(const char *path, const char *func) {
static wontreturn void SysDie(const char *path, const char *func) {
const char *errstr;
if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN";
Print(2, path, ": ", func, " failed with ", errstr, "\n", NULL);
tinyprint(2, path, ": ", func, " failed with ", errstr, "\n", NULL);
exit(1);
}
static wontreturn void PrintUsage(int fd, int exitcode) {
Print(fd, "\
tinyprint(fd, "\
NAME\n\
\n\
Cosmopolitan Zip Copier\n\
@ -71,7 +59,7 @@ NAME\n\
SYNOPSIS\n\
\n\
",
program_invocation_name, " [FLAGS] SRC DST\n\
program_invocation_name, " [FLAGS] SRC DST\n\
\n\
DESCRIPTION\n\
\n\
@ -96,7 +84,7 @@ EXAMPLE\n\
\n\
\n\
",
NULL);
NULL);
exit(exitcode);
}
@ -173,10 +161,10 @@ static void CopyZip(void) {
// write output
if ((outfd = open(outpath, O_WRONLY | O_CREAT, 0644)) == -1) {
SysExit(outpath, "open");
SysDie(outpath, "open");
}
if ((outsize = lseek(outfd, 0, SEEK_END)) == -1) {
SysExit(outpath, "lseek");
SysDie(outpath, "lseek");
}
ldest = outsize;
cdest = outsize + ltotal;
@ -186,23 +174,23 @@ static void CopyZip(void) {
// write local file
length = ZIP_LFILE_SIZE(lfile);
if (pwrite(outfd, lfile, length, ldest) != length) {
SysExit(outpath, "lfile pwrite");
SysDie(outpath, "lfile pwrite");
}
ldest += length;
// write directory entry
length = ZIP_CFILE_HDRSIZE(cfile);
if (pwrite(outfd, cfile, length, cdest) != length) {
SysExit(outpath, "lfile pwrite");
SysDie(outpath, "lfile pwrite");
}
cdest += length;
}
WRITE32LE(eocd + kZipCdirOffsetOffset, outsize + ltotal);
length = ZIP_CDIR_HDRSIZE(eocd);
if (pwrite(outfd, eocd, length, cdest) != length) {
SysExit(outpath, "eocd pwrite");
SysDie(outpath, "eocd pwrite");
}
if (close(outfd)) {
SysExit(outpath, "close");
SysDie(outpath, "close");
}
}
@ -213,23 +201,23 @@ int main(int argc, char *argv[]) {
}
GetOpts(argc, argv);
if ((infd = open(inpath, O_RDONLY)) == -1) {
SysExit(inpath, "open");
SysDie(inpath, "open");
}
if ((insize = lseek(infd, 0, SEEK_END)) == -1) {
SysExit(inpath, "lseek");
SysDie(inpath, "lseek");
}
if (!insize) {
Die(inpath, "file is empty");
}
if ((inmap = mmap(0, insize, PROT_READ | PROT_WRITE, MAP_PRIVATE, infd, 0)) ==
MAP_FAILED) {
SysExit(inpath, "mmap");
SysDie(inpath, "mmap");
}
CopyZip();
if (munmap(inmap, insize)) {
SysExit(inpath, "munmap");
SysDie(inpath, "munmap");
}
if (close(infd)) {
SysExit(inpath, "close");
SysDie(inpath, "close");
}
}

View file

@ -21,7 +21,6 @@
#include "libc/elf/def.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/libgen.h"
#include "libc/intrin/kprintf.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
@ -52,15 +51,16 @@ int strip_components_;
const char *path_prefix_;
struct timespec timestamp;
wontreturn void PrintUsage(int rc) {
kprintf("\n\
wontreturn void PrintUsage(int fd, int rc) {
tinyprint(fd, "\n\
NAME\n\
\n\
Cosmpolitan Zip File Compiler\n\
\n\
SYNOPSIS\n\
\n\
%s [FLAGS] FILE...\n\
",
program_invocation_name, " [FLAGS] FILE...\n\
\n\
DESCRIPTION\n\
\n\
@ -80,7 +80,7 @@ FLAGS\n\
-y SYMBOL generate yoink for symbol (default __zip_eocd)\n\
\n\
",
program_invocation_name);
NULL);
exit(rc);
}
@ -117,17 +117,18 @@ void GetOpts(int *argc, char ***argv) {
break;
case '?':
case 'h':
PrintUsage(EXIT_SUCCESS);
PrintUsage(1, EXIT_SUCCESS);
default:
PrintUsage(EX_USAGE);
PrintUsage(2, EX_USAGE);
}
}
*argc -= optind;
*argv += optind;
if (!outpath_) {
kprintf("error: no output path specified\n"
"run %s -h for usage\n",
program_invocation_name);
tinyprint(2,
"error: no output path specified\n"
"run ",
program_invocation_name, " -h for usage\n", NULL);
exit(1);
}
}

View file

@ -1,101 +0,0 @@
#include "libc/nt/struct/peb.h"
#include "libc/stdio/stdio.h"
int main() {
printf("InheritedAddressSpace = 0x%x\n",
offsetof(struct NtPeb, InheritedAddressSpace));
printf("ReadImageFileExecOptions = 0x%x\n",
offsetof(struct NtPeb, ReadImageFileExecOptions));
printf("BeingDebugged = 0x%x\n", offsetof(struct NtPeb, BeingDebugged));
printf("Mutant = 0x%x\n", offsetof(struct NtPeb, Mutant));
printf("ImageBaseAddress = 0x%x\n", offsetof(struct NtPeb, ImageBaseAddress));
printf("Ldr = 0x%x\n", offsetof(struct NtPeb, Ldr));
printf("ProcessParameters = 0x%x\n",
offsetof(struct NtPeb, ProcessParameters));
printf("SubSystemData = 0x%x\n", offsetof(struct NtPeb, SubSystemData));
printf("ProcessHeap = 0x%x\n", offsetof(struct NtPeb, ProcessHeap));
printf("FastPebLock = 0x%x\n", offsetof(struct NtPeb, FastPebLock));
printf("KernelCallbackTable = 0x%x\n",
offsetof(struct NtPeb, KernelCallbackTable));
printf("UserSharedInfoPtr = 0x%x\n",
offsetof(struct NtPeb, UserSharedInfoPtr));
printf("SystemReserved = 0x%x\n", offsetof(struct NtPeb, SystemReserved));
printf("__wut6 = 0x%x\n", offsetof(struct NtPeb, __wut6));
printf("__wut7 = 0x%x\n", offsetof(struct NtPeb, __wut7));
printf("TlsExpansionCounter = 0x%x\n",
offsetof(struct NtPeb, TlsExpansionCounter));
printf("TlsBitmap = 0x%x\n", offsetof(struct NtPeb, TlsBitmap));
printf("TlsBitmapBits = 0x%x\n", offsetof(struct NtPeb, TlsBitmapBits));
printf("ReadOnlySharedMemoryBase = 0x%x\n",
offsetof(struct NtPeb, ReadOnlySharedMemoryBase));
printf("ReadOnlyStaticServerData = 0x%x\n",
offsetof(struct NtPeb, ReadOnlyStaticServerData));
printf("AnsiCodePageData = 0x%x\n", offsetof(struct NtPeb, AnsiCodePageData));
printf("OemCodePageData = 0x%x\n", offsetof(struct NtPeb, OemCodePageData));
printf("UnicodeCaseTableData = 0x%x\n",
offsetof(struct NtPeb, UnicodeCaseTableData));
printf("NumberOfProcessors = 0x%x\n",
offsetof(struct NtPeb, NumberOfProcessors));
printf("NtGlobalFlag = 0x%x\n", offsetof(struct NtPeb, NtGlobalFlag));
printf("CriticalSectionTimeout = 0x%x\n",
offsetof(struct NtPeb, CriticalSectionTimeout));
printf("HeapSegmentReserve = 0x%x\n",
offsetof(struct NtPeb, HeapSegmentReserve));
printf("HeapSegmentCommit = 0x%x\n",
offsetof(struct NtPeb, HeapSegmentCommit));
printf("HeapDeCommitTotalFreeThreshold = 0x%x\n",
offsetof(struct NtPeb, HeapDeCommitTotalFreeThreshold));
printf("HeapDeCommitFreeBlockThreshold = 0x%x\n",
offsetof(struct NtPeb, HeapDeCommitFreeBlockThreshold));
printf("NumberOfHeaps = 0x%x\n", offsetof(struct NtPeb, NumberOfHeaps));
printf("MaximumNumberOfHeaps = 0x%x\n",
offsetof(struct NtPeb, MaximumNumberOfHeaps));
printf("ProcessHeaps = 0x%x\n", offsetof(struct NtPeb, ProcessHeaps));
printf("GdiSharedHandleTable = 0x%x\n",
offsetof(struct NtPeb, GdiSharedHandleTable));
printf("ProcessStarterHelper = 0x%x\n",
offsetof(struct NtPeb, ProcessStarterHelper));
printf("GdiDCAttributeList = 0x%x\n",
offsetof(struct NtPeb, GdiDCAttributeList));
printf("LoaderLock = 0x%x\n", offsetof(struct NtPeb, LoaderLock));
printf("OSMajorVersion = 0x%x\n", offsetof(struct NtPeb, OSMajorVersion));
printf("OSMinorVersion = 0x%x\n", offsetof(struct NtPeb, OSMinorVersion));
printf("OSVersion = 0x%x\n", offsetof(struct NtPeb, OSVersion));
printf("OSBuildNumber = 0x%x\n", offsetof(struct NtPeb, OSBuildNumber));
printf("OSCSDVersion = 0x%x\n", offsetof(struct NtPeb, OSCSDVersion));
printf("OSPlatformId = 0x%x\n", offsetof(struct NtPeb, OSPlatformId));
printf("ImageSubsystem = 0x%x\n", offsetof(struct NtPeb, ImageSubsystem));
printf("ImageSubsystemMajorVersion = 0x%x\n",
offsetof(struct NtPeb, ImageSubsystemMajorVersion));
printf("ImageSubsystemMinorVersion = 0x%x\n",
offsetof(struct NtPeb, ImageSubsystemMinorVersion));
printf("ImageProcessAffinityMask = 0x%x\n",
offsetof(struct NtPeb, ImageProcessAffinityMask));
printf("ActiveProcessAffinityMask = 0x%x\n",
offsetof(struct NtPeb, ActiveProcessAffinityMask));
printf("GdiHandleBuffer = 0x%x\n", offsetof(struct NtPeb, GdiHandleBuffer));
printf("PostProcessInitRoutine = 0x%x\n",
offsetof(struct NtPeb, PostProcessInitRoutine));
printf("TlsExpansionBitmap = 0x%x\n",
offsetof(struct NtPeb, TlsExpansionBitmap));
printf("TlsExpansionBitmapBits = 0x%x\n",
offsetof(struct NtPeb, TlsExpansionBitmapBits));
printf("SessionId = 0x%x\n", offsetof(struct NtPeb, SessionId));
printf("AppCompatFlags = 0x%x\n", offsetof(struct NtPeb, AppCompatFlags));
printf("AppCompatFlagsUser = 0x%x\n",
offsetof(struct NtPeb, AppCompatFlagsUser));
printf("pShimData = 0x%x\n", offsetof(struct NtPeb, pShimData));
printf("AppCompatInfo = 0x%x\n", offsetof(struct NtPeb, AppCompatInfo));
printf("CSDVersion = 0x%x\n", offsetof(struct NtPeb, CSDVersion));
printf("ActivationContextData = 0x%x\n",
offsetof(struct NtPeb, ActivationContextData));
printf("ProcessAssemblyStorageMap = 0x%x\n",
offsetof(struct NtPeb, ProcessAssemblyStorageMap));
printf("SystemDefaultActivationContextData = 0x%x\n",
offsetof(struct NtPeb, SystemDefaultActivationContextData));
printf("SystemAssemblyStorageMap = 0x%x\n",
offsetof(struct NtPeb, SystemAssemblyStorageMap));
printf("MinimumStackCommit = 0x%x\n",
offsetof(struct NtPeb, MinimumStackCommit));
return 0;
}

View file

@ -1,202 +0,0 @@
/*-*- 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.
THIS PROGRAM TURNS TEXT LIKE THIS
+------------------------------------------------------------------------+
| Button | Name | Go to | From 1.2.3 |
| | | | go to |
|------------+-------------+--------------------------------+------------|
| [ < ] | Back | previous section in reading | 1.2.2 |
| | | order | |
|------------+-------------+--------------------------------+------------|
| [ > ] | Forward | next section in reading order | 1.2.4 |
|------------+-------------+--------------------------------+------------|
| [ << ] | FastBack | previous or up-and-previous | 1.1 |
| | | section | |
|------------+-------------+--------------------------------+------------|
| [ Up ] | Up | up section | 1.2 |
|------------+-------------+--------------------------------+------------|
| [ >> ] | FastForward | next or up-and-next section | 1.3 |
|------------+-------------+--------------------------------+------------|
| [Top] | Top | cover (top) of document | |
|------------+-------------+--------------------------------+------------|
| [Contents] | Contents | table of contents | |
|------------+-------------+--------------------------------+------------|
| [Index] | Index | concept index | |
|------------+-------------+--------------------------------+------------|
| [ ? ] | About | this page | |
+------------------------------------------------------------------------+
INTO THIS
Button Name Go to From 1.2.3
go to
[ < ] Back previous section in reading 1.2.2
order
[ > ] Forward next section in reading order 1.2.4
[ << ] FastBack previous or upandprevious 1.1
section
[ Up ] Up up section 1.2
[ >> ] FastForward next or upandnext section 1.3
[Top] Top cover (top) of document
[Contents] Contents table of contents
[Index] Index concept index
[ ? ] About this page
*/
#include "libc/macros.internal.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/str/strwidth.h"
#include "libc/x/x.h"
#include "libc/x/xasprintf.h"
#include "libc/x/xgetline.h"
#define IsSpace(C) ((C) == ' ')
#define IsPipe(C) ((C) == '|' || (C) == u'│')
#define IsPlus(C) ((C) == '+' || (C) == u'┼')
#define IsHyphen(C) ((C) == '-' || (C) == u'─')
#define IsTick(C) ((C) == '`' || (C) == u'└')
#define IsPipe(C) ((C) == '|' || (C) == u'│')
#define IsEquals(C) ((C) == '=' || (C) == u'═')
int n;
int yn;
int xn;
FILE *f;
bool *V;
char **T;
char16_t **L;
static void DoIt(int y, int x) {
if (V[y * (xn + 1) + x]) return;
V[y * (xn + 1) + x] = 1;
if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPlus(L[y][x]) &&
IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) {
L[y][x] = u'';
} else if (IsPipe(L[y - 1][x]) && IsEquals(L[y][x - 1]) && IsPlus(L[y][x]) &&
IsEquals(L[y][x + 1]) && IsPipe(L[y + 1][x])) {
L[y][x] = u'';
} else if (IsSpace(L[y - 1][x]) && IsHyphen(L[y][x - 1]) &&
IsHyphen(L[y][x]) && IsHyphen(L[y][x + 1]) &&
IsPipe(L[y + 1][x])) {
L[y][x] = u'';
} else if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) &&
IsHyphen(L[y][x]) && IsHyphen(L[y][x + 1]) &&
IsSpace(L[y + 1][x])) {
L[y][x] = u'';
} else if (IsPipe(L[y - 1][x]) && IsSpace(L[y][x - 1]) && IsPipe(L[y][x]) &&
IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) {
L[y][x] = u'';
} else if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPipe(L[y][x]) &&
IsSpace(L[y][x + 1]) && IsPipe(L[y + 1][x])) {
L[y][x] = u'';
} else if (IsSpace(L[y - 1][x]) && IsSpace(L[y][x - 1]) && IsPlus(L[y][x]) &&
IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) {
L[y][x] = u'';
} else if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPlus(L[y][x]) &&
IsSpace(L[y][x + 1]) && IsSpace(L[y + 1][x])) {
L[y][x] = u'';
} else if (IsSpace(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPlus(L[y][x]) &&
IsSpace(L[y][x + 1]) && IsPipe(L[y + 1][x])) {
L[y][x] = u'';
} else if (IsPipe(L[y - 1][x]) && IsSpace(L[y][x - 1]) && IsPlus(L[y][x]) &&
IsHyphen(L[y][x + 1]) && IsSpace(L[y + 1][x])) {
L[y][x] = u'';
} else if (IsTick(L[y][x]) && IsPipe(L[y - 1][x]) && IsHyphen(L[y][x + 1]) &&
IsSpace(L[y + 1][x]) && IsSpace(L[y][x - 1])) {
L[y][x] = u'';
} else if (IsHyphen(L[y][x])) {
L[y][x] = u'';
} else if (IsPipe(L[y][x])) {
L[y][x] = u'';
} else if (IsEquals(L[y][x])) {
L[y][x] = u'';
} else {
return;
}
DoIt(y - 1, x + 0);
DoIt(y + 1, x + 0);
DoIt(y + 0, x - 1);
DoIt(y + 0, x + 1);
}
int main(int argc, char *argv[]) {
char *s;
int y, x;
ShowCrashReports();
f = stdin;
while ((s = _chomp(xgetline(f)))) {
n = strwidth(s, 0);
xn = MAX(xn, n);
T = xrealloc(T, ++yn * sizeof(*T));
T[yn - 1] = s;
}
xn += 1000;
L = xmalloc((yn + 2) * sizeof(*L));
L[0] = utf8to16(_gc(xasprintf(" %*s ", xn, " ")), -1, 0);
for (y = 0; y < yn; ++y) {
s = xasprintf(" %s%*s ", T[y], xn - n, " ");
L[y + 1] = utf8to16(s, -1, 0);
free(T[y]);
free(s);
}
L[yn + 2 - 1] = utf8to16(_gc(xasprintf(" %*s ", xn, " ")), -1, 0);
free(T);
V = xcalloc((yn + 1) * (xn + 1), 1);
for (y = 1; y <= yn; ++y) {
for (x = 1; x <= xn; ++x) {
if (IsPipe(L[y - 1][x]) && IsHyphen(L[y][x - 1]) && IsPlus(L[y][x]) &&
IsHyphen(L[y][x + 1]) && IsPipe(L[y + 1][x])) {
DoIt(y, x);
}
if (IsTick(L[y][x]) && IsPipe(L[y - 1][x]) && IsHyphen(L[y][x + 1]) &&
IsSpace(L[y + 1][x]) && IsSpace(L[y][x - 1])) {
DoIt(y, x);
}
}
}
for (y = 1; y + 1 < yn; ++y) {
s = utf16to8(L[y], -1, 0);
n = strlen(s);
while (n && s[n - 1] == ' ') s[n - 1] = 0, --n;
puts(s + 1);
free(s);
}
for (y = 0; y < yn; ++y) {
free(L[y]);
}
free(L);
free(V);
return 0;
}

View file

@ -1,284 +0,0 @@
/*-*- 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/struct/stat.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/x/xasprintf.h"
#include "libc/x/xiso8601.h"
#include "libc/zip.internal.h"
#include "tool/decode/lib/asmcodegen.h"
#include "tool/decode/lib/disassemblehex.h"
#include "tool/decode/lib/zipnames.h"
char *FormatDosDate(uint16_t dosdate) {
return xasprintf("%04u-%02u-%02u", ((dosdate >> 9) & 0b1111111) + 1980,
(dosdate >> 5) & 0b1111, dosdate & 0b11111);
}
char *FormatDosTime(uint16_t dostime) {
return xasprintf("%02u:%02u:%02u", (dostime >> 11) & 0b11111,
(dostime >> 5) & 0b111111, (dostime << 1) & 0b111110);
}
void ShowGeneralFlag(uint16_t generalflag) {
puts("\
/ utf8\n\
/ strong encryption\n\
/ compressed patch data\n\
/ crc and size go after file content\n\
/ {normal,max,fast,superfast}\n\
/ encrypted\n\
/ rrrruuuur");
show(".short", format(b1, "0b%016b", generalflag), "generalflag");
}
void ShowCompressionMethod(uint16_t compressmethod) {
show(".short",
firstnonnull(findnamebyid(kZipCompressionNames, compressmethod),
format(b1, "%hu", compressmethod)),
"compressionmethod");
}
void ShowTimestamp(uint16_t time, uint16_t date) {
show(".short", format(b1, "%#04hx", time),
_gc(xasprintf("%s (%s)", "lastmodifiedtime", _gc(FormatDosTime(time)))));
show(".short", format(b1, "%#04hx", date),
_gc(xasprintf("%s (%s)", "lastmodifieddate", _gc(FormatDosDate(date)))));
}
void ShowNtfs(uint8_t *ntfs, size_t n) {
struct timespec mtime, atime, ctime;
mtime = WindowsTimeToTimeSpec(READ64LE(ntfs + 8));
atime = WindowsTimeToTimeSpec(READ64LE(ntfs + 16));
ctime = WindowsTimeToTimeSpec(READ64LE(ntfs + 24));
show(".long", _gc(xasprintf("%d", READ32LE(ntfs))), "ntfs reserved");
show(".short", _gc(xasprintf("0x%04x", READ16LE(ntfs + 4))),
"ntfs attribute tag value #1");
show(".short", _gc(xasprintf("%hu", READ16LE(ntfs + 6))),
"ntfs attribute tag size");
show(".quad", _gc(xasprintf("%lu", READ64LE(ntfs + 8))),
_gc(xasprintf("%s (%s)", "ntfs last modified time",
_gc(xiso8601(&mtime)))));
show(".quad", _gc(xasprintf("%lu", READ64LE(ntfs + 16))),
_gc(xasprintf("%s (%s)", "ntfs last access time",
_gc(xiso8601(&atime)))));
show(".quad", _gc(xasprintf("%lu", READ64LE(ntfs + 24))),
_gc(xasprintf("%s (%s)", "ntfs creation time", _gc(xiso8601(&ctime)))));
}
void ShowExtendedTimestamp(uint8_t *p, size_t n, bool islocal) {
int flag;
if (n) {
--n;
flag = *p++;
show(".byte", _gc(xasprintf("0b%03hhb", flag)), "fields present in local");
if ((flag & 1) && n >= 4) {
show(".long", _gc(xasprintf("%u", READ32LE(p))),
_gc(xasprintf("%s (%s)", "last modified",
_gc(xiso8601(&(struct timespec){READ32LE(p)})))));
p += 4;
n -= 4;
}
flag >>= 1;
if (islocal) {
if ((flag & 1) && n >= 4) {
show(".long", _gc(xasprintf("%u", READ32LE(p))),
_gc(xasprintf("%s (%s)", "access time",
_gc(xiso8601(&(struct timespec){READ32LE(p)})))));
p += 4;
n -= 4;
}
flag >>= 1;
if ((flag & 1) && n >= 4) {
show(".long", _gc(xasprintf("%u", READ32LE(p))),
_gc(xasprintf("%s (%s)", "creation time",
_gc(xiso8601(&(struct timespec){READ32LE(p)})))));
p += 4;
n -= 4;
}
}
}
}
void ShowZip64(uint8_t *p, size_t n, bool islocal) {
if (n >= 8) {
show(".quad", _gc(xasprintf("%lu", READ64LE(p))),
_gc(xasprintf("uncompressed size (%,ld)", READ64LE(p))));
}
if (n >= 16) {
show(".quad", _gc(xasprintf("%lu", READ64LE(p + 8))),
_gc(xasprintf("compressed size (%,ld)", READ64LE(p + 8))));
}
if (n >= 24) {
show(".quad", _gc(xasprintf("%lu", READ64LE(p + 16))),
_gc(xasprintf("lfile hdr offset (%,ld)", READ64LE(p + 16))));
}
if (n >= 28) {
show(".long", _gc(xasprintf("%u", READ32LE(p + 24))), "disk number");
}
}
void ShowInfoZipNewUnixExtra(uint8_t *p, size_t n, bool islocal) {
if (p[0] == 1 && p[1] == 4 && p[6] == 4) {
show(".byte", "1", "version");
show(".byte", "4", "uid length");
show(".long", _gc(xasprintf("%u", READ32LE(p + 2))), "uid");
show(".byte", "4", "gid length");
show(".long", _gc(xasprintf("%u", READ32LE(p + 7))), "gid");
} else {
disassemblehex(p, n, stdout);
}
}
void ShowExtra(uint8_t *extra, bool islocal) {
switch (ZIP_EXTRA_HEADERID(extra)) {
case kZipExtraNtfs:
ShowNtfs(ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra));
break;
case kZipExtraExtendedTimestamp:
ShowExtendedTimestamp(ZIP_EXTRA_CONTENT(extra),
ZIP_EXTRA_CONTENTSIZE(extra), islocal);
break;
case kZipExtraZip64:
ShowZip64(ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra),
islocal);
break;
case kZipExtraInfoZipNewUnixExtra:
ShowInfoZipNewUnixExtra(ZIP_EXTRA_CONTENT(extra),
ZIP_EXTRA_CONTENTSIZE(extra), islocal);
break;
default:
disassemblehex(ZIP_EXTRA_CONTENT(extra), ZIP_EXTRA_CONTENTSIZE(extra),
stdout);
break;
}
}
void ShowExtras(uint8_t *extras, uint16_t extrassize, bool islocal) {
int i;
bool first;
uint8_t *p, *pe;
if (extrassize) {
first = true;
for (p = extras, pe = extras + extrassize, i = 0; p < pe;
p += ZIP_EXTRA_SIZE(p), ++i) {
show(".short",
firstnonnull(findnamebyid(kZipExtraNames, ZIP_EXTRA_HEADERID(p)),
_gc(xasprintf("0x%04hx", ZIP_EXTRA_HEADERID(p)))),
_gc(xasprintf("%s[%d].%s", "extras", i, "headerid")));
show(".short", _gc(xasprintf("%df-%df", (i + 2) * 10, (i + 1) * 10)),
_gc(xasprintf("%s[%d].%s (%hd %s)", "extras", i, "contentsize",
ZIP_EXTRA_CONTENTSIZE(p), "bytes")));
if (first) {
first = false;
printf("%d:", (i + 1) * 10);
}
ShowExtra(p, islocal);
printf("%d:", (i + 2) * 10);
}
}
putchar('\n');
}
void ShowLocalFileHeader(uint8_t *lf, uint16_t idx) {
printf("\n/\t%s #%hu (%zu %s)\n", "local file", idx + 1,
ZIP_LFILE_HDRSIZE(lf), "bytes");
show(".ascii", format(b1, "%`'.*s", 4, lf), "magic");
show(".byte",
firstnonnull(findnamebyid(kZipEraNames, ZIP_LFILE_VERSIONNEED(lf)),
_gc(xasprintf("%d", ZIP_LFILE_VERSIONNEED(lf)))),
"pkzip version need");
show(".byte",
firstnonnull(findnamebyid(kZipOsNames, ZIP_LFILE_OSNEED(lf)),
_gc(xasprintf("%d", ZIP_LFILE_OSNEED(lf)))),
"os need");
ShowGeneralFlag(ZIP_LFILE_GENERALFLAG(lf));
ShowCompressionMethod(ZIP_LFILE_COMPRESSIONMETHOD(lf));
ShowTimestamp(ZIP_LFILE_LASTMODIFIEDTIME(lf), ZIP_LFILE_LASTMODIFIEDDATE(lf));
show(
".long",
format(b1, "%#x", ZIP_LFILE_CRC32(lf)), _gc(xasprintf("%s (%#x)", "crc32z", GetZipLfileCompressedSize(lf) /* crc32_z(0, ZIP_LFILE_CONTENT(lf), GetZipLfileCompressedSize(lf)) */)));
if (ZIP_LFILE_COMPRESSEDSIZE(lf) == 0xFFFFFFFF) {
show(".long", "0xFFFFFFFF", "compressedsize (zip64)");
} else {
show(".long", "3f-2f",
format(b1, "%s (%u %s)", "compressedsize",
ZIP_LFILE_COMPRESSEDSIZE(lf), "bytes"));
}
show(".long",
ZIP_LFILE_UNCOMPRESSEDSIZE(lf) == 0xFFFFFFFF
? "0xFFFFFFFF"
: format(b1, "%u", ZIP_LFILE_UNCOMPRESSEDSIZE(lf)),
"uncompressedsize");
show(".short", "1f-0f",
format(b1, "%s (%hu %s)", "namesize", ZIP_LFILE_NAMESIZE(lf), "bytes"));
show(
".short", "2f-1f",
format(b1, "%s (%hu %s)", "extrasize", ZIP_LFILE_EXTRASIZE(lf), "bytes"));
printf("0:");
show(".ascii",
format(b1, "%`'s",
_gc(strndup(ZIP_LFILE_NAME(lf), ZIP_LFILE_NAMESIZE(lf)))),
"name");
printf("1:");
ShowExtras(ZIP_LFILE_EXTRA(lf), ZIP_LFILE_EXTRASIZE(lf), true);
printf("2:");
disassemblehex(ZIP_LFILE_CONTENT(lf), ZIP_LFILE_COMPRESSEDSIZE(lf), stdout);
printf("3:\n");
}
void DisassembleZip(const char *path, uint8_t *p, size_t n) {
size_t i, records;
uint8_t *eocd, *cdir, *cf, *lf;
CHECK_NOTNULL((eocd = GetZipEocd(p, n, 0)));
records = GetZipCdirRecords(eocd);
cdir = p + GetZipCdirOffset(eocd);
for (i = 0, cf = cdir; i < records; ++i, cf += ZIP_CFILE_HDRSIZE(cf)) {
CHECK_EQ(kZipCfileHdrMagic, ZIP_CFILE_MAGIC(cf));
lf = p + GetZipCfileOffset(cf);
CHECK_EQ(kZipLfileHdrMagic, ZIP_LFILE_MAGIC(lf));
ShowLocalFileHeader(lf, i);
}
}
int main(int argc, char *argv[]) {
int fd;
uint8_t *map;
struct stat st;
ShowCrashReports();
CHECK_EQ(2, argc);
CHECK_NE(-1, (fd = open(argv[1], O_RDONLY)));
CHECK_NE(-1, fstat(fd, &st));
CHECK_GE(st.st_size, kZipCdirHdrMinSize);
CHECK_NE(MAP_FAILED,
(map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
DisassembleZip(argv[1], map, st.st_size);
CHECK_NE(-1, munmap(map, st.st_size));
CHECK_NE(-1, close(fd));
return 0;
}

View file

@ -1,4 +1,3 @@
(require 'ctest-mode)
(require 'ld-script)
(require 'optinfo-mode)
(require 'protobuf-mode)

View file

@ -1,115 +0,0 @@
(defconst ctest-operators
'("+"
"-"
"*"
"/"
"%"
"//"
"**"
"~"
"^"
"|"
"&"
">>"
"<<"
"!"
"||"
"&&"
"="
"!="
"<"
">"
"<="
">="))
(defconst ctest-consts
'("false"
"true"
"e"
"pi"
"epsilon"
"inf"
"nan"
"l2t"
"lg2"
"ln2"
"l2e"))
(defconst ctest-builtins
'("emit"
"exit"
"meminfo"
"isnan"
"isinf"
"signbit"
"isfinite"
"isnormal"
"fpclassify"))
(defconst ctest-functions
'("emit"
"cr"
"key"
"dup"
"swap"
"over"
"drop"
"expect"
"assert"
"abs"
"min"
"max"))
(defconst ctest-functions-libm
'("mod"
"rem"
"gray"
"ungray"
"popcnt"
"sqrt"
"exp"
"exp2"
"exp10"
"ldexp"
"log"
"log2"
"log10"
"sin"
"cos"
"tan"
"asin"
"acos"
"atan"
"atan2"
"round"
"trunc"
"rint"
"nearbyint"
"ceil"
"floor"
"rand"
"rand64"))
(defun ctest--make-regex (words)
(concat "\\_<" (regexp-opt words) "\\_>"))
(defconst ctest-highlights
`(("\\(#.*\\)$" 1 font-lock-comment-face)
("\\b0\\([xX]\\)[[:xdigit:]]+\\([ulUL]*\\)\\b"
(1 font-lock-constant-face)
(2 font-lock-constant-face))
("\\b0\\([bB]\\)[01]+\\([ulUL]*\\)\\b"
(1 font-lock-constant-face)
(2 font-lock-constant-face))
(,(concat "\\_<" (regexp-opt ctest-consts) "\\_>") .
font-lock-constant-face)
(,(concat "\\_<" (regexp-opt ctest-builtins) "\\_>") .
font-lock-builtin-face)))
(define-derived-mode ctest-mode fundamental-mode "CALCULATOR.COM"
"Major mode for editing CALCULATOR.COM smoke tests."
(setq font-lock-defaults '(ctest-highlights)))
(add-to-list 'auto-mode-alist '("\\.ctest$" . ctest-mode))
(provide 'ctest-mode)

View file

@ -1,315 +0,0 @@
/*-*- 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
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/fmt/conv.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/math.h"
#include "libc/mem/gc.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/lcg.internal.h"
#include "libc/stdio/rand.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/x/x.h"
#include "third_party/gdtoa/gdtoa.h"
#include "third_party/getopt/getopt.internal.h"
#include "tool/viz/lib/formatstringtable.h"
typedef double (*round_f)(double);
typedef unsigned long (*rand_f)(void);
struct Range {
long double a;
long double b;
};
short xn_ = 8;
short yn_ = 8;
double digs_ = 6;
rand_f rand_;
round_f rounder_;
const char *path_ = "-";
const char *name_ = "M";
const char *type_ = "float";
struct Range r1_ = {LONG_MIN, LONG_MAX};
struct Range r2_ = {0, 1};
StringTableFormatter *formatter_ = FormatStringTableAsCode;
static wontreturn void PrintUsage(int rc, FILE *f) {
fprintf(f, "Usage: %s%s", program_invocation_name, "\
[FLAGS] [FILE]\n\
\n\
Flags:\n\
-u unsigned\n\
-c char\n\
-s short\n\
-i int\n\
-l long\n\
-d double\n\
-b bytes [-uc]\n\
-g non-deterministic rng\n\
-S output assembly\n\
-W output whitespace\n\
-o PATH output path\n\
-x FLEX\n\
-w FLEX width\n\
-y FLEX\n\
-h FLEX height\n\
-N NAME name\n\
-T NAME type name\n\
-A FLEX min value\n\
-B FLEX max value\n\
-R FUNC round function for indexing\n\
-D FLEX decimal digits to printout\n\
-v increases verbosity\n\
-? shows this information\n\
\n");
exit(rc);
}
static bool StringEquals(const char *a, const char *b) {
return strcasecmp(a, b) == 0;
}
static wontreturn void ShowInvalidArg(const char *name, const char *s,
const char *type) {
fprintf(stderr, "error: invalid %s %s: %s\n", type, name, s);
exit(EXIT_FAILURE);
}
static double ParseFlexidecimalOrDie(const char *name, const char *s,
double min, double max) {
double x;
s = firstnonnull(s, "NULL");
if (strchr(s, '.') || strchr(s, 'e')) {
x = strtod(s, NULL);
} else {
x = strtol(s, NULL, 0);
}
if (min <= x && x <= max) {
return x;
} else {
ShowInvalidArg(name, s, "flexidecimal");
}
}
static round_f ParseRoundingFunctionOrDie(const char *s) {
if (isempty(s) || StringEquals(s, "none") || StringEquals(s, "null")) {
return NULL;
} else if (StringEquals(s, "round")) {
return round;
} else if (StringEquals(s, "rint")) {
return rint;
} else if (StringEquals(s, "nearbyint")) {
return nearbyint;
} else if (StringEquals(s, "trunc")) {
return trunc;
} else if (StringEquals(s, "floor")) {
return floor;
} else if (StringEquals(s, "ceil")) {
return ceil;
} else {
ShowInvalidArg("round", s, "func");
}
}
static void ConfigureIntegralRange(const char *type, long min, long max) {
type_ = type;
r1_.a = min;
r1_.b = max;
r2_.a = min;
r2_.b = max;
if (!rounder_) rounder_ = round;
}
void GetOpts(int argc, char *argv[]) {
int opt;
bool want_unsigned, want_char, want_short, want_int, want_long, want_double;
want_unsigned = false;
want_char = false;
want_short = false;
want_int = false;
want_long = false;
want_double = false;
if (argc == 2 &&
(StringEquals(argv[1], "--help") || StringEquals(argv[1], "-help"))) {
PrintUsage(EXIT_SUCCESS, stdout);
}
while ((opt = getopt(argc, argv, "?vubcsildgSWo:x:w:y:h:N:A:B:C:E:T:R:D:")) !=
-1) {
switch (opt) {
case 'b':
want_unsigned = true;
want_char = true;
break;
case 'u':
want_unsigned = true;
break;
case 'c':
want_char = true;
break;
case 's':
want_short = true;
break;
case 'i':
want_int = true;
break;
case 'l':
want_long = true;
break;
case 'd':
want_double = true;
break;
case 'g':
rand_ = _rand64;
break;
case 'N':
name_ = optarg;
break;
case 'o':
path_ = optarg;
break;
case 'S':
formatter_ = FormatStringTableAsAssembly;
break;
case 'W':
formatter_ = FormatStringTableBasic;
break;
case 't':
type_ = optarg;
break;
case 'x':
case 'w':
xn_ = ParseFlexidecimalOrDie("width", optarg, 1, SHRT_MAX);
break;
case 'y':
case 'h':
yn_ = ParseFlexidecimalOrDie("height", optarg, 1, SHRT_MAX);
break;
case 'D':
digs_ = ParseFlexidecimalOrDie("digs", optarg, 0, 15.95);
break;
case 'r':
rounder_ = ParseRoundingFunctionOrDie(optarg);
break;
case 'A':
r1_.a = ParseFlexidecimalOrDie("r1_.a", optarg, INT_MIN, INT_MAX);
break;
case 'B':
r1_.b = ParseFlexidecimalOrDie("r1_.b", optarg, INT_MIN, INT_MAX);
break;
case 'C':
r2_.a = ParseFlexidecimalOrDie("r2_.a", optarg, INT_MIN, INT_MAX);
break;
case 'E':
r2_.b = ParseFlexidecimalOrDie("r2_.b", optarg, INT_MIN, INT_MAX);
break;
case '?':
PrintUsage(EXIT_SUCCESS, stdout);
default:
PrintUsage(EX_USAGE, stderr);
}
}
if (want_unsigned && want_char) {
ConfigureIntegralRange("unsigned char", 0, 255);
} else if (want_char) {
ConfigureIntegralRange("signed char", -128, 127);
} else if (want_unsigned && want_short) {
ConfigureIntegralRange("unsigned short", USHRT_MIN, USHRT_MAX);
} else if (want_short) {
ConfigureIntegralRange("short", SHRT_MIN, SHRT_MAX);
} else if (want_unsigned && want_int) {
ConfigureIntegralRange("unsigned", UINT_MIN, UINT_MAX);
} else if (want_int) {
ConfigureIntegralRange("int", INT_MIN, INT_MAX);
} else if (want_unsigned && want_long) {
ConfigureIntegralRange("unsigned long", ULONG_MIN, ULONG_MAX);
} else if (want_long) {
ConfigureIntegralRange("long", LONG_MIN, LONG_MAX);
} else if (want_double) {
type_ = "double";
r1_.a = LONG_MIN;
r1_.b = LONG_MAX;
digs_ = 19;
}
}
static void *SetRandom(long n, long p[n]) {
long i;
uint64_t r;
if (rand_) {
for (r = 1, i = 0; i < n; ++i) {
p[i] = rand_();
}
} else {
for (r = 1, i = 0; i < n; ++i) {
p[i] = KnuthLinearCongruentialGenerator(&r) >> 32 |
KnuthLinearCongruentialGenerator(&r) >> 32 << 32;
}
}
return p;
}
static long double ConvertRange(long double x, long double a, long double b,
long double c, long double d) {
return (d - c) / (b - a) * (x - a) + c;
}
static double Compand(long x, double a, double b, double c, double d) {
return ConvertRange(ConvertRange(x, LONG_MIN, LONG_MAX, a, b), a, b, c, d);
}
static void GenerateMatrixImpl(long I[yn_][xn_], double M[yn_][xn_], FILE *f) {
long y, x;
for (y = 0; y < yn_; ++y) {
for (x = 0; x < xn_; ++x) {
M[y][x] = Compand(I[y][x], r1_.a, r1_.b, r2_.a, r2_.b);
}
if (rounder_) {
for (x = 0; x < xn_; ++x) {
M[y][x] = rounder_(M[y][x]);
}
}
}
FormatMatrixDouble(yn_, xn_, M, fputs, f, formatter_, type_, name_, NULL,
digs_, round);
}
void GenerateMatrix(FILE *f) {
GenerateMatrixImpl(SetRandom(yn_ * xn_, gc(calloc(yn_ * xn_, sizeof(long)))),
gc(calloc(yn_ * xn_, sizeof(double))), f);
}
int main(int argc, char *argv[]) {
int i;
FILE *f;
ShowCrashReports();
GetOpts(argc, argv);
CHECK_NOTNULL((f = fopen(path_, "w")));
if (optind < argc) FATALF("TODO(jart): support input files");
GenerateMatrix(f);
return fclose(f);
}

View file

@ -1,116 +0,0 @@
/*-*- 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
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/log/check.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/exit.h"
#include "third_party/getopt/getopt.internal.h"
static FILE *fi_, *fo_;
static char *inpath_, *outpath_;
wontreturn void usage(int rc, FILE *f) {
fprintf(f, "%s%s%s\n", "Usage: ", program_invocation_name,
" [-o FILE] [FILE...]\n");
exit(rc);
}
void getopts(int *argc, char *argv[]) {
int opt;
outpath_ = "-";
while ((opt = getopt(*argc, argv, "?ho:")) != -1) {
switch (opt) {
case 'o':
outpath_ = optarg;
break;
case '?':
case 'h':
usage(EXIT_SUCCESS, stdout);
default:
usage(EX_USAGE, stderr);
}
}
if (optind == *argc) {
argv[(*argc)++] = "-";
}
}
void processfile(void) {
wint_t wc;
while ((wc = fgetwc(fi_)) != -1) {
switch (wc) {
case L'':
wc = L' ';
break;
case L'':
wc = L'';
break;
case L'':
wc = L'';
break;
case L'':
wc = L'';
break;
/* █ */
case L'':
wc = L'';
break;
case L'':
wc = L'';
break;
case L'':
wc = L'';
break;
case L'':
wc = L'';
break;
case L'':
wc = L'';
break;
case L'':
wc = L'';
break;
case L'':
wc = L'';
break;
case L'':
wc = L'';
break;
default:
break;
}
fputwc(wc, fo_);
}
}
int main(int argc, char *argv[]) {
size_t i;
getopts(&argc, argv);
CHECK_NOTNULL((fo_ = fopen(outpath_, "w")));
for (i = optind; i < argc; ++i) {
CHECK_NOTNULL((fi_ = fopen((inpath_ = argv[i]), "r")));
processfile();
CHECK_NE(-1, fclose(fi_));
fi_ = 0;
}
CHECK_NE(-1, fclose(fo_));
fo_ = 0;
return 0;
}

View file

@ -1,642 +0,0 @@
/*-*- 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
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 "dsp/core/c1331.h"
#include "dsp/core/c161.h"
#include "dsp/core/core.h"
#include "dsp/scale/scale.h"
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/fmt/conv.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/macros.internal.h"
#include "libc/math.h"
#include "libc/mem/gc.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/rand.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/testlib/testlib.h"
#include "libc/x/x.h"
#include "third_party/getopt/getopt.internal.h"
#include "third_party/stb/stb_image.h"
#include "tool/viz/lib/bilinearscale.h"
#include "tool/viz/lib/graphic.h"
#define LONG long
#define CHAR char
#define CLAMP(X) MIN(255, MAX(0, X))
#define C13(A, B) (((A) + 3 * (B) + 2) >> 2)
#define LERP(X, Y, P) ((X) + (((P) * ((Y) - (X))) >> 8))
static double r_;
static unsigned char ChessBoard(unsigned y, unsigned x, unsigned char a,
unsigned char b) {
return !((y ^ x) & (1u << 2)) ? a : b;
}
static unsigned char AlphaBackground(unsigned y, unsigned x) {
return ChessBoard(y, x, 255, 200);
}
static unsigned char OutOfBoundsBackground(unsigned y, unsigned x) {
return ChessBoard(y, x, 40, 80);
}
static unsigned char Opacify(CHAR w, const unsigned char P[1u << w][1u << w],
const unsigned char A[1u << w][1u << w], LONG yn,
LONG xn, long y, long x) {
if ((0 <= y && y < yn) && (0 <= x && x < xn)) {
return LERP(AlphaBackground(y, x), P[y][x], A[y][x]);
} else {
return OutOfBoundsBackground(y, x);
}
}
static void PrintImage(CHAR w, unsigned char R[1u << w][1u << w],
unsigned char G[1u << w][1u << w],
unsigned char B[1u << w][1u << w],
unsigned char A[1u << w][1u << w], LONG yn, LONG xn) {
bool didhalfy;
long y, x;
didhalfy = false;
for (y = 0; y < yn; y += 2) {
if (y) printf("\e[0m\n");
for (x = 0; x < xn; ++x) {
printf("\e[48;2;%d;%d;%d;38;2;%d;%d;%dm▄",
Opacify(w, R, A, yn, xn, y + 0, x),
Opacify(w, G, A, yn, xn, y + 0, x),
Opacify(w, B, A, yn, xn, y + 0, x),
Opacify(w, R, A, yn, xn, y + 1, x),
Opacify(w, G, A, yn, xn, y + 1, x),
Opacify(w, B, A, yn, xn, y + 1, x));
}
if (y == 0) {
printf("\e[0m‾0");
} else if (yn / 2 <= y && y <= yn / 2 + 1 && !didhalfy) {
printf("\e[0m‾%s%s", "yn/2", y % 2 ? "+1" : "");
didhalfy = true;
} else if (y + 1 == yn / 2 && !didhalfy) {
printf("\e[0m⎯yn/2");
didhalfy = true;
} else if (y + 1 == yn) {
printf("\e[0m⎯yn");
} else if (y + 2 == yn) {
printf("\e[0m_yn");
} else if (!(y % 10)) {
printf("\e[0m‾%,u", y);
}
}
printf("\e[0m\n");
}
static void DeblinterlaceRgba(CHAR w, unsigned char R[1u << w][1u << w],
unsigned char G[1u << w][1u << w],
unsigned char B[1u << w][1u << w],
unsigned char A[1u << w][1u << w], LONG yn,
LONG xn, const unsigned char src[yn][xn][4]) {
long y, x;
for (y = 0; y < yn; ++y) {
for (x = 0; x < xn; ++x) {
R[y][x] = src[y][x][0];
G[y][x] = src[y][x][1];
B[y][x] = src[y][x][2];
A[y][x] = src[y][x][3];
}
}
}
static void SharpenX(CHAR w, unsigned char dst[1u << w][1u << w],
const unsigned char src[1u << w][1u << w], char yw,
char xw) {
int y, x;
for (y = 0; y < (1u << yw); ++y) {
for (x = 0; x < (1u << xw); ++x) {
dst[y][x] = C161(src[y][MAX(0, x - 1)], src[y][x],
src[y][MIN((1u << xw) - 1, x + 1)]);
}
}
}
static void SharpenY(CHAR w, unsigned char dst[1u << w][1u << w],
const unsigned char src[1u << w][1u << w], char yw,
char xw) {
int y, x;
for (y = 0; y < (1u << yw); ++y) {
for (x = 0; x < (1u << xw); ++x) {
dst[y][x] = C161(src[MAX(0, y - 1)][x], src[y][x],
src[MIN((1u << yw) - 1, y + 1)][x]);
}
}
}
static void UpscaleX(CHAR w, unsigned char img[1u << w][1u << w], char yw,
char xw) {
long y, x;
for (y = (1u << yw); y--;) {
for (x = (1u << xw); --x;) {
img[y][x] =
C13(img[y][MIN(((1u << xw) >> 1) - 1, (x >> 1) - 1 + (x & 1) * 2)],
img[y][x >> 1]);
}
}
}
static void UpscaleY(CHAR w, unsigned char img[1u << w][1u << w], char yw,
char xw) {
long y, x;
for (y = (1u << yw); --y;) {
for (x = (1u << xw); x--;) {
img[y][x] =
C13(img[MIN(((1u << yw) >> 1) - 1, (y >> 1) - 1 + (y & 1) * 2)][x],
img[y >> 1][x]);
}
}
}
static void Upscale(CHAR w, unsigned char img[1u << w][1u << w],
unsigned char tmp[1u << w][1u << w], char yw, char xw) {
UpscaleY(w, img, yw, xw - 1);
SharpenY(w, tmp, img, yw, xw - 1);
UpscaleX(w, tmp, yw, xw);
SharpenX(w, img, tmp, yw, xw);
}
#if 0
static void *MagikarpY(CHAR w, unsigned char p[1u << w][1u << w], char yw,
char xw) {
long y, x, yn, xn, ym;
unsigned char(*t)[(1u << w) + 2][1u << w];
t = memalign(64, ((1u << w) + 2) * (1u << w));
bzero(t, ((1u << w) + 2) * (1u << w));
yn = 1u << yw;
xn = 1u << xw;
ym = yn >> 1;
for (y = 0; y < ym; ++y) {
for (x = 0; x < xn; ++x) {
(*t)[y + 1][x] =
C1331(y ? p[(y << 1) - 1][x] : 0, p[y << 1][x], p[(y << 1) + 1][x],
p[MIN(yn - 1, (y << 1) + 2)][x]);
}
}
for (y = 0; y < ym; ++y) {
for (x = 0; x < xn; ++x) {
p[y][x] =
C161((*t)[y + 1 - 1][x], (*t)[y + 1 + 0][x], (*t)[y + 1 + 1][x]);
}
}
free(t);
return p;
}
static void *MagikarpX(CHAR w, unsigned char p[1u << w][1u << w], char yw,
char xw) {
int y, x;
LONG yn, xn, xm;
yn = 1u << yw;
xn = 1u << xw;
xm = xn >> 1;
for (x = 0; x < xm; ++x) {
for (y = 0; y < yn; ++y) {
p[y][(xn - xm - 1) + (xm - x - 1)] =
C1331(p[y][MAX(00 + 0, xn - (x << 1) - 1 + (xn & 1) - 1)],
p[y][MIN(xn - 1, xn - (x << 1) - 1 + (xn & 1) + 0)],
p[y][MIN(xn - 1, xn - (x << 1) - 1 + (xn & 1) + 1)],
p[y][MIN(xn - 1, xn - (x << 1) - 1 + (xn & 1) + 2)]);
}
}
for (x = 0; x < xm; ++x) {
for (y = 0; y < yn; ++y) {
p[y][x] = C161(p[y][MAX(xn - 1 - xm, xn - xm - 1 + x - 1)],
p[y][MIN(xn - 1 - 00, xn - xm - 1 + x + 0)],
p[y][MIN(xn - 1 - 00, xn - xm - 1 + x + 1)]);
}
}
return p;
}
static void ProcessImageVerbatim(LONG yn, LONG xn,
unsigned char img[yn][xn][4]) {
CHAR w;
void *R, *G, *B, *A;
w = _roundup2log(MAX(yn, xn));
R = xvalloc((1u << w) * (1u << w));
G = xvalloc((1u << w) * (1u << w));
B = xvalloc((1u << w) * (1u << w));
A = xvalloc((1u << w) * (1u << w));
DeblinterlaceRgba(w, R, G, B, A, yn, xn, img);
PrintImage(w, R, G, B, A, yn, xn);
free(R);
free(G);
free(B);
free(A);
}
static void ProcessImageDouble(LONG yn, LONG xn, unsigned char img[yn][xn][4]) {
CHAR w;
void *t, *R, *G, *B, *A;
w = _roundup2log(MAX(yn, xn)) + 1;
t = xvalloc((1u << w) * (1u << w));
R = xvalloc((1u << w) * (1u << w));
G = xvalloc((1u << w) * (1u << w));
B = xvalloc((1u << w) * (1u << w));
A = xvalloc((1u << w) * (1u << w));
DeblinterlaceRgba(w, R, G, B, A, yn, xn, img);
Upscale(w, R, t, w, w);
Upscale(w, G, t, w, w);
Upscale(w, B, t, w, w);
Upscale(w, A, t, w, w);
free(t);
PrintImage(w, R, G, B, A, yn * 2, xn * 2);
free(R);
free(G);
free(B);
free(A);
}
static void ProcessImageHalf(LONG yn, LONG xn, unsigned char img[yn][xn][4]) {
CHAR w;
void *R, *G, *B, *A;
w = _roundup2log(MAX(yn, xn));
R = xvalloc((1u << w) * (1u << w));
G = xvalloc((1u << w) * (1u << w));
B = xvalloc((1u << w) * (1u << w));
A = xvalloc((1u << w) * (1u << w));
DeblinterlaceRgba(w, R, G, B, A, yn, xn, img);
MagikarpY(w, R, w, w);
MagikarpY(w, G, w, w);
MagikarpY(w, B, w, w);
MagikarpY(w, A, w, w);
MagikarpX(w, R, w - 1, w);
MagikarpX(w, G, w - 1, w);
MagikarpX(w, B, w - 1, w);
MagikarpX(w, A, w - 1, w);
PrintImage(w, R, G, B, A, yn >> 1, xn >> 1);
free(R);
free(G);
free(B);
free(A);
}
static void ProcessImageHalfY(LONG yn, LONG xn, unsigned char img[yn][xn][4]) {
CHAR w;
void *R, *G, *B, *A;
w = _roundup2log(MAX(yn, xn));
R = xvalloc((1u << w) * (1u << w));
G = xvalloc((1u << w) * (1u << w));
B = xvalloc((1u << w) * (1u << w));
A = xvalloc((1u << w) * (1u << w));
DeblinterlaceRgba(w, R, G, B, A, yn, xn, img);
MagikarpY(w, R, w, w);
MagikarpY(w, G, w, w);
MagikarpY(w, B, w, w);
MagikarpY(w, A, w, w);
PrintImage(w, R, G, B, A, yn >> 1, xn);
free(R);
free(G);
free(B);
free(A);
}
static void ProcessImageHalfLanczos(LONG yn, LONG xn,
unsigned char img[yn][xn][4]) {
CHAR w;
void *t, *R, *G, *B, *A;
t = xvalloc((yn >> 1) * (xn >> 1) * 4);
lanczos1b(yn >> 1, xn >> 1, t, yn, xn, &img[0][0][0]);
w = _roundup2log(MAX(yn >> 1, xn >> 1));
R = xvalloc((1u << w) * (1u << w));
G = xvalloc((1u << w) * (1u << w));
B = xvalloc((1u << w) * (1u << w));
A = xvalloc((1u << w) * (1u << w));
DeblinterlaceRgba(w, R, G, B, A, yn >> 1, xn >> 1, img);
free(t);
PrintImage(w, R, G, B, A, yn >> 1, xn >> 1);
free(R);
free(G);
free(B);
free(A);
}
static void ProcessImageWash(LONG yn, LONG xn, unsigned char img[yn][xn][4]) {
long w;
void *R, *G, *B, *A, *t;
w = _roundup2log(MAX(yn, xn)) + 1;
t = xvalloc((1u << w) * (1u << w));
R = xvalloc((1u << w) * (1u << w));
G = xvalloc((1u << w) * (1u << w));
B = xvalloc((1u << w) * (1u << w));
A = xvalloc((1u << w) * (1u << w));
DeblinterlaceRgba(w, R, G, B, A, yn, xn, img);
Upscale(w, R, t, w, w);
Upscale(w, G, t, w, w);
Upscale(w, B, t, w, w);
Upscale(w, A, t, w, w);
MagikarpY(w, R, w, w);
MagikarpY(w, G, w, w);
MagikarpY(w, B, w, w);
MagikarpY(w, A, w, w);
MagikarpX(w, R, w - 1, w);
MagikarpX(w, G, w - 1, w);
MagikarpX(w, B, w - 1, w);
MagikarpX(w, A, w - 1, w);
free(t);
PrintImage(w, R, G, B, A, yn, xn);
free(R);
free(G);
free(B);
free(A);
}
#endif
#if 0
static void *MagikarpY(size_t ys, size_t xs, unsigned char p[ys][xs], size_t yn,
size_t xn) {
int y, x, h, b;
b = yn % 2;
h = yn / 2;
if (b && yn < ys) yn++;
for (y = b; y < h + b; ++y) {
for (x = 0; x < xn; ++x) {
p[(yn - h - 1) + (h - y - 1)][x] =
C1331(p[MAX(00 + 0, yn - y * 2 - 1 - 1)][x],
p[MIN(yn - 1, yn - y * 2 - 1 + 0)][x],
p[MIN(yn - 1, yn - y * 2 - 1 + 1)][x],
p[MIN(yn - 1, yn - y * 2 - 1 + 2)][x]);
}
}
for (y = b; y < h + b; ++y) {
for (x = 0; x < xn; ++x) {
p[y][x] = C161(p[MAX(yn - 1 - h, yn - h - 1 + y - 1)][x],
p[MIN(yn - 1 - 0, yn - h - 1 + y + 0)][x],
p[MIN(yn - 1 - 0, yn - h - 1 + y + 1)][x]);
}
}
return p;
}
#endif
#if 0
static void *MagikarpX(size_t ys, size_t xs, unsigned char p[ys][xs], size_t yn,
size_t xn) {
int y, x, w, b;
b = xn % 2;
w = xn / 2;
if (b && xn < xs) xn++;
for (x = 0; x < w; ++x) {
for (y = b; y < yn + b; ++y) {
p[y][(xn - w - 1) + (w - x - 1)] =
C1331(p[y][MAX(00 + 0, xn - x * 2 - 1 - 1)],
p[y][MIN(xn - 1, xn - x * 2 - 1 + 0)],
p[y][MIN(xn - 1, xn - x * 2 - 1 + 1)],
p[y][MIN(xn - 1, xn - x * 2 - 1 + 2)]);
}
}
for (x = 0; x < w; ++x) {
for (y = b; y < yn + b; ++y) {
p[y][x] = C161(p[y][MAX(xn - 1 - w, xn - w - 1 + x - 1)],
p[y][MIN(xn - 1 - 0, xn - w - 1 + x + 0)],
p[y][MIN(xn - 1 - 0, xn - w - 1 + x + 1)]);
}
}
return p;
}
#endif
#if 0
static void ProcessImageMagikarpImpl(CHAR sw,
unsigned char src[5][1u << sw][1u << sw],
LONG syn, LONG sxn,
const unsigned char img[syn][sxn][4],
LONG dyn, LONG dxn) {
DeblinterlaceRgba2(sw, src, syn, sxn, img);
MagikarpY(sw, src[0], sw, sw);
MagikarpX(sw, src[0], sw - 1, sw);
MagikarpY(sw, src[1], sw, sw);
MagikarpX(sw, src[1], sw - 1, sw);
MagikarpY(sw, src[2], sw, sw);
MagikarpX(sw, src[2], sw - 1, sw);
BilinearScale(sw, src[4], sw, src[3], dyn, dxn, syn, sxn);
memcpy(src[3], src[4], syn * sxn);
PrintImage2(sw, src, dyn, dxn);
}
static void ProcessImageMagikarp(LONG syn, LONG sxn,
unsigned char img[syn][sxn][4]) {
CHAR sw;
LONG dyn, dxn;
dyn = syn >> 1;
dxn = sxn >> 1;
sw = _roundup2log(MAX(syn, sxn));
ProcessImageMagikarpImpl(sw, gc(xvalloc((1u << sw) * (1u << sw) * 5)), syn,
sxn, img, dyn, dxn);
}
#endif
/*
********************************************************************************
*/
static unsigned char Opacify2(unsigned yw, unsigned xw,
const unsigned char P[yw][xw],
const unsigned char A[yw][xw], unsigned yn,
unsigned xn, unsigned y, unsigned x) {
if ((0 <= y && y < yn) && (0 <= x && x < xn)) {
return LERP(AlphaBackground(y, x), P[y][x], A[y][x]);
} else {
return OutOfBoundsBackground(y, x);
}
}
static dontinline void PrintImage2(unsigned yw, unsigned xw,
unsigned char img[4][yw][xw], unsigned yn,
unsigned xn) {
bool didhalfy;
unsigned y, x;
didhalfy = false;
for (y = 0; y < yn; y += 2) {
if (y) printf("\e[0m\n");
for (x = 0; x < xn; ++x) {
printf("\e[48;2;%d;%d;%d;38;2;%d;%d;%dm▄",
Opacify2(yw, xw, img[0], img[3], yn, xn, y + 0, x),
Opacify2(yw, xw, img[1], img[3], yn, xn, y + 0, x),
Opacify2(yw, xw, img[2], img[3], yn, xn, y + 0, x),
Opacify2(yw, xw, img[0], img[3], yn, xn, y + 1, x),
Opacify2(yw, xw, img[1], img[3], yn, xn, y + 1, x),
Opacify2(yw, xw, img[2], img[3], yn, xn, y + 1, x));
}
if (y == 0) {
printf("\e[0m‾0");
} else if (yn / 2 <= y && y <= yn / 2 + 1 && !didhalfy) {
printf("\e[0m‾%s%s", "yn/2", y % 2 ? "+1" : "");
didhalfy = true;
} else if (y + 1 == yn / 2 && !didhalfy) {
printf("\e[0m⎯yn/2");
didhalfy = true;
} else if (y + 1 == yn) {
printf("\e[0m⎯yn");
} else if (y + 2 == yn) {
printf("\e[0m_yn");
} else if (!(y % 10)) {
printf("\e[0m‾%,u", y);
}
}
printf("\e[0m\n");
}
static dontinline void *DeblinterlaceRgba2(unsigned yn, unsigned xn,
unsigned char D[4][yn][xn],
const unsigned char S[yn][xn][4]) {
unsigned y, x;
for (y = 0; y < yn; ++y) {
for (x = 0; x < xn; ++x) {
D[0][y][x] = S[y][x][0];
D[1][y][x] = S[y][x][1];
D[2][y][x] = S[y][x][2];
D[3][y][x] = S[y][x][3];
}
}
return D;
}
void ProcessImageBilinearImpl(unsigned dyn, unsigned dxn,
unsigned char dst[4][dyn][dxn], unsigned syn,
unsigned sxn, unsigned char src[4][syn][sxn],
unsigned char img[syn][sxn][4]) {
DeblinterlaceRgba2(syn, sxn, src, img);
BilinearScale(4, dyn, dxn, dst, 4, syn, sxn, src, 0, 4, dyn, dxn, syn, sxn,
r_, r_, 0, 0);
PrintImage2(dyn, dxn, dst, dyn, dxn);
}
void ProcessImageBilinear(unsigned yn, unsigned xn,
unsigned char img[yn][xn][4]) {
unsigned dyn, dxn;
dyn = lround(yn / r_);
dxn = lround(xn / r_);
ProcessImageBilinearImpl(dyn, dxn, gc(xmalloc(dyn * dxn * 4)), yn, xn,
gc(xmalloc(yn * xn * 4)), img);
}
static void *b2f(long n, float dst[n], const unsigned char src[n]) {
long i;
float f;
for (i = 0; i < n; ++i) {
f = src[i];
f *= 1 / 255.;
dst[i] = f;
}
return dst;
}
static void *f2b(long n, unsigned char dst[n], const float src[n]) {
int x;
long i;
for (i = 0; i < n; ++i) {
x = lroundf(src[i] * 255);
dst[i] = MIN(255, MAX(0, x));
}
return dst;
}
void ProcessImageGyarados(unsigned yn, unsigned xn,
unsigned char img[yn][xn][4]) {
unsigned dyn, dxn;
dyn = lround(yn / r_);
dxn = lround(xn / r_);
PrintImage2(
dyn, dxn,
EzGyarados(4, dyn, dxn, gc(xmalloc(dyn * dxn * 4)), 4, yn, xn,
DeblinterlaceRgba2(yn, xn, gc(xmalloc(yn * xn * 4)), img), 0,
4, dyn, dxn, yn, xn, r_, r_, 0, 0),
dyn, dxn);
}
void MagikarpDecimate(int yw, int xw, unsigned char img[4][yw][xw], int yn,
int xn, int n) {
int c;
if (n <= 1) {
PrintImage2(yw, xw, img, yn, xn);
} else {
for (c = 0; c < 4; ++c) Magikarp2xY(yw, xw, img[c], yn, xn);
for (c = 0; c < 4; ++c) Magikarp2xX(yw, xw, img[c], (yn + 1) / 2, xn);
MagikarpDecimate(yw, xw, img, (yn + 1) / 2, (xn + 1) / 2, (n + 1) / 2);
}
}
void ProcessImageMagikarp(unsigned yn, unsigned xn,
unsigned char img[yn][xn][4]) {
MagikarpDecimate(yn, xn,
DeblinterlaceRgba2(yn, xn, gc(xmalloc(yn * xn * 4)), img),
yn, xn, lround(r_));
}
dontinline void WithImageFile(const char *path,
void fn(unsigned yn, unsigned xn,
unsigned char img[yn][xn][4])) {
struct stat st;
int fd, yn, xn;
void *map, *data;
CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path);
CHECK_NE(-1, fstat(fd, &st));
CHECK_GT(st.st_size, 0);
CHECK_LE(st.st_size, INT_MAX);
fadvise(fd, 0, 0, MADV_WILLNEED | MADV_SEQUENTIAL);
CHECK_NE(MAP_FAILED,
(map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
CHECK_NOTNULL(
(data = stbi_load_from_memory(map, st.st_size, &xn, &yn, NULL, 4)), "%s",
path);
CHECK_NE(-1, munmap(map, st.st_size));
CHECK_NE(-1, close(fd));
fn(yn, xn, data);
free(data);
}
int main(int argc, char *argv[]) {
int i, opt;
bool bilinear;
void (*scaler)(unsigned yn, unsigned xn, unsigned char[yn][xn][4]) =
ProcessImageMagikarp;
r_ = 2;
while ((opt = getopt(argc, argv, "mlsSybr:")) != -1) {
switch (opt) {
case 'r':
r_ = strtod(optarg, NULL);
break;
case 'm':
scaler = ProcessImageMagikarp;
break;
case 's':
case 'S':
scaler = ProcessImageGyarados;
break;
case 'b':
scaler = ProcessImageBilinear;
break;
default:
break;
}
}
ShowCrashReports();
for (i = optind; i < argc; ++i) {
WithImageFile(argv[i], scaler);
}
return 0;
}

View file

@ -1,95 +0,0 @@
#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/internal.h"
#include "libc/fmt/conv.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/bits.h"
#include "libc/macros.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/stdio/stdio.h"
// clang-format off
struct WinArgs {
char *argv[4096];
char *envp[4092];
intptr_t auxv[2][2];
char argblock[ARG_MAX / 2];
char envblock[ARG_MAX / 2];
};
//#define INCREMENT _roundup2pow(kAutomapSize/16)
#define INCREMENT (64L*1024*1024*1024)
uint64_t last;
void plan2(uint64_t addr, uint64_t end, const char *name) {
char sz[32];
sizefmt(sz, end-addr+1, 1024);
printf("%08x-%08x %-6s %s\n", addr>>16, end>>16, sz, name);
}
void plan(uint64_t addr, uint64_t end, const char *name) {
uint64_t incr, next;
while (addr > last) {
if ((incr = last % INCREMENT)) {
incr = INCREMENT - incr;
} else {
incr = INCREMENT;
}
plan2(last,MIN(last+incr,addr)-1,"free");
last = MIN(last+incr,addr);
}
while (addr <= end) {
if (end-addr+1 <= INCREMENT) {
plan2(addr,end,name);
last = end + 1;
break;
}
if (!(addr % INCREMENT)) {
plan2(addr, addr + INCREMENT - 1, name);
last = addr + INCREMENT;
addr += INCREMENT;
} else {
next = INCREMENT - addr % INCREMENT + addr;
plan2(addr, next - 1, name);
last = next;
addr = next;
}
}
}
int main(int argc, char *argv[]) {
uint64_t x, y;
plan(0x00000000, 0x00200000-1, "null");
plan(0x00200000, 0x00400000-1, "loader");
if (!IsWindows() || IsAtLeastWindows10()) {
plan(0x00400000, 0x50000000-1, "image");
plan(0x50000000, 0x7ffdffff, "arena");
plan(0x7fff0000, 0x10007fffffff, "asan");
} else {
plan(0x00400000, 0x01000000-1, "image");
}
plan(kAutomapStart, kAutomapStart + kAutomapSize - 1, "automap");
plan(kMemtrackStart, kMemtrackStart + kMemtrackSize - 1, "memtrack");
plan(kFixedmapStart, kFixedmapStart + kFixedmapSize - 1, "fixedmap");
if (IsWindows() && !IsAtLeastWindows10()) {
plan(0x50000000, 0x7ffdffff, "arena");
}
x = GetStaticStackAddr(0);
y = ROUNDUP(sizeof(struct WinArgs), FRAMESIZE);
plan(x - y, x - 1, "winargs");
plan(x, x + GetStackSize() - 1, "stack");
if (!IsWindows() || IsAtLeastWindows10()) {
plan(0x7f0000000000, 0x800000000000 - 1, "kernel");
}
return 0;
}

View file

@ -1,83 +0,0 @@
/*-*- 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/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/x/xgetline.h"
#define DLL "iphlpapi"
/**
* @fileoverview Tool for adding rnew libraries to libc/nt/master.sh
*
* If provided with a /tmp/syms.txt file containing one symbol name per
* line, this tool will output the correctly tab indented shell code.
*/
int main(int argc, char *argv[]) {
FILE *f;
int i, n, t;
char *sym, tabs[64];
ShowCrashReports();
f = fopen("/tmp/syms.txt", "r");
memset(tabs, '\t', 64);
while ((sym = _chomp(xgetline(f)))) {
if (strlen(sym)) {
printf("imp\t");
/* what we call the symbol */
i = printf("'%s'", sym);
t = 0;
n = 56;
if (i % 8) ++t, i = ROUNDUP(i, 8);
t += (n - i) / 8;
printf("%.*s", t, tabs);
/* what the kernel dll calls the symbol */
i = printf("%s", sym);
t = 0;
n = 56;
if (i % 8) ++t, i = ROUNDUP(i, 8);
t += (n - i) / 8;
printf("%.*s", t, tabs);
/* dll short name */
i = printf("%s", DLL);
t = 0;
n = 16;
if (i % 8) ++t, i = ROUNDUP(i, 8);
t += (n - i) / 8;
printf("%.*s", t, tabs);
/* hint */
i = printf("0");
t = 0;
n = 8;
if (i % 8) ++t, i = ROUNDUP(i, 8);
t += (n - i) / 8;
printf("%.*s", t, tabs);
printf("\n");
}
free(sym);
}
return 0;
}

View file

@ -1,45 +0,0 @@
/*-*- 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
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 "dsp/tty/quant.h"
#include "dsp/tty/xtermname.h"
#include "libc/fmt/conv.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ex.h"
int main(int argc, char *argv[]) {
int i;
struct TtyRgb tty;
unsigned rgb, r, g, b;
if (argc < 2) {
fprintf(stderr, "Usage: %s RRGGBB...\n", program_invocation_name);
exit(EX_USAGE);
}
for (i = 1; i < argc; ++i) {
rgb = strtol(argv[i], NULL, 16);
b = (rgb & 0x0000ff) >> 000;
g = (rgb & 0x00ff00) >> 010;
r = (rgb & 0xff0000) >> 020;
tty = rgb2tty(r, g, b);
printf("\e[48;5;%dm \e[0m %d \\e[48;5;%dm %s #%02x%02x%02x\n", tty.xt,
tty.xt, tty.xt, IndexDoubleNulString(kXtermName, tty.xt), r, g, b);
}
return 0;
}

View file

@ -1,135 +0,0 @@
/*-*- 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
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 "dsp/tty/quant.h"
#include "libc/calls/calls.h"
#include "libc/log/check.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.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/fileno.h"
#include "third_party/getopt/getopt.internal.h"
#define kUsage \
"Usage:\n\
\n\
%s [-cber] [-o FILE] [ARGS...]\n\
\n\
Flags:\n\
\n\
-e enable emphasis\n\
-b emit as background color\n\
-r print raw codes\n\
-c emit cleanup (reset) codes when done\n\
-o FILE redirects output [default: /dev/stdout]\n\
\n\
Arguments:\n\
\n\
- may be passed via ARGS or STDIN (one per line)\n\
- may be #RRGGBB or RRGGBB\n\
- may be #RGB or RGB (#123 #112233)\n\
- anything else is printed verbatim\n\
\n"
static FILE *fout_;
static size_t linecap_;
static char *outpath_, *line_;
static bool rawmode_, background_, emphasis_, cleanup_;
wontreturn void usage(int rc, FILE *f) {
fprintf(f, kUsage, program_invocation_name);
exit(rc);
}
void getopts(int *argc, char *argv[]) {
int opt;
outpath_ = "-";
while ((opt = getopt(*argc, argv, "?hrecbo:")) != -1) {
switch (opt) {
case 'r':
rawmode_ = true;
break;
case 'b':
background_ = true;
break;
case 'c':
cleanup_ = true;
break;
case 'e':
emphasis_ = true;
break;
case 'o':
outpath_ = optarg;
break;
case '?':
case 'h':
usage(EXIT_SUCCESS, stdout);
default:
usage(EX_USAGE, stderr);
}
}
}
void processarg(const char *arg) {
const char *p;
size_t r, g, b;
if (*(p = arg) == '#') p++;
if (strlen(p) == 3 && (isxdigit(p[0]) && isxdigit(p[1]) && isxdigit(p[2]))) {
r = hextoint(p[0]) << 4 | hextoint(p[0]);
g = hextoint(p[1]) << 4 | hextoint(p[1]);
b = hextoint(p[2]) << 4 | hextoint(p[2]);
} else if (strlen(p) == 6 &&
(isxdigit(p[0]) && isxdigit(p[1]) && isxdigit(p[2]) &&
isxdigit(p[3]) && isxdigit(p[4]) && isxdigit(p[5]))) {
r = hextoint(p[0]) << 4 | hextoint(p[1]);
g = hextoint(p[2]) << 4 | hextoint(p[3]);
b = hextoint(p[4]) << 4 | hextoint(p[5]);
} else {
fputs(arg, fout_);
return;
}
fprintf(fout_, "%s[%s%d;5;%hhum%s", rawmode_ ? "\e" : "\\e",
emphasis_ ? "1;" : "", background_ ? 48 : 38, rgb2tty(r, g, b).xt,
&"\n"[rawmode_]);
}
int main(int argc, char *argv[]) {
size_t i;
getopts(&argc, argv);
CHECK_NOTNULL((fout_ = fopen(outpath_, "w")));
if (optind < argc) {
for (i = optind; i < argc; ++i) {
processarg(argv[i]);
}
} else {
while ((getline(&line_, &linecap_, stdin)) != -1) {
processarg(_chomp(line_));
}
free(line_);
line_ = 0;
}
if (cleanup_) {
fprintf(fout_, "%s[0m\n", rawmode_ ? "\e" : "\\e");
}
CHECK_NE(-1, fclose(fout_));
fout_ = 0;
return 0;
}

View file

@ -1,177 +0,0 @@
/*-*- 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
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/fmt/conv.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/mem/arraylist.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/str/strwidth.h"
#include "libc/str/unicode.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/exit.h"
#include "third_party/getopt/getopt.internal.h"
#define kOneTrueTabWidth 8
struct Pool {
size_t i, n;
char *p;
};
struct Lines {
size_t i, n;
struct Line {
uint16_t off;
uint16_t col;
int32_t line;
} * p;
};
static bool chunk_;
static FILE *fi_, *fo_;
static struct Pool pool_;
static struct Lines lines_;
static size_t mincol_, col_, maxcol_, linecap_;
static char *inpath_, *outpath_, *delim_, *line_;
wontreturn void usage(int rc, FILE *f) {
fprintf(f, "%s%s%s\n", "Usage: ", program_invocation_name,
" [-c] [-m MINCOL] [-M MAXCOL] [-F DELIM] [-o FILE] [FILE...]\n"
"\n"
" This program aligns monospace text. It's aware of tabs,\n"
" color codes, wide characters, combining characters etc.\n");
exit(rc);
}
void getopts(int *argc, char *argv[]) {
int opt;
delim_ = "#";
outpath_ = "-";
while ((opt = getopt(*argc, argv, "?hco:m:M:F:")) != -1) {
switch (opt) {
case 'm':
mincol_ = strtol(optarg, NULL, 0);
break;
case 'M':
maxcol_ = strtol(optarg, NULL, 0);
break;
case 'c':
chunk_ = true;
break;
case 'o':
outpath_ = optarg;
break;
case 'F':
delim_ = optarg;
break;
case '?':
case 'h':
usage(EXIT_SUCCESS, stdout);
default:
usage(EX_USAGE, stderr);
}
}
if (optind == *argc) {
argv[(*argc)++] = "-";
}
}
void flush(void) {
size_t i, j;
const char *s;
struct Line l;
col_ = roundup(col_ + 1, kOneTrueTabWidth);
if (maxcol_) col_ = min(col_, maxcol_);
for (i = 0; i < lines_.i; ++i) {
l = lines_.p[i];
s = &pool_.p[l.line];
if (l.off < USHRT_MAX) {
fwrite(s, l.off, 1, fo_);
for (j = l.col; j < col_;) {
fputc('\t', fo_);
if (j % kOneTrueTabWidth == 0) {
j += 8;
} else {
j += kOneTrueTabWidth - (j & (kOneTrueTabWidth - 1));
}
}
fwrite(s + l.off, strlen(s) - l.off, 1, fo_);
} else {
fwrite(s, strlen(s), 1, fo_);
}
fputc('\n', fo_);
}
col_ = mincol_;
pool_.i = 0;
lines_.i = 0;
}
void processfile(void) {
char *p;
int col, s;
size_t off, len;
while ((getline(&line_, &linecap_, fi_)) != -1) {
_chomp(line_);
len = strlen(line_);
s = concat(&pool_, line_, len + 1);
if (len < USHRT_MAX) {
if ((p = strstr(line_, delim_))) {
off = p - line_;
col = strnwidth(line_, off, 0);
if (col < USHRT_MAX) {
col_ = max(col_, col);
append(&lines_, &((struct Line){.line = s, .off = off, .col = col}));
continue;
}
} else {
if (chunk_) {
flush();
fputs(line_, fo_);
fputc('\n', fo_);
continue;
}
}
}
append(&lines_, &((struct Line){.line = s, .off = 0xffff, .col = 0xffff}));
}
}
int main(int argc, char *argv[]) {
size_t i;
getopts(&argc, argv);
CHECK_NOTNULL((fo_ = fopen(outpath_, "w")));
for (i = optind; i < argc; ++i) {
CHECK_NOTNULL((fi_ = fopen((inpath_ = argv[i]), "r")));
processfile();
CHECK_NE(-1, fclose(fi_));
fi_ = 0;
}
flush();
CHECK_NE(-1, fclose(fo_));
fo_ = 0;
free(lines_.p);
free(pool_.p);
free(line_);
return 0;
}

View file

@ -1,156 +0,0 @@
#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/intrin/bits.h"
#include "libc/stdio/stdio.h"
// clang-format off
static char ip[] = "\
\x45\x00\x00\x3c\xc8\xbc\x40\x00\x40\x06\x48\xf6\x7f\x0a\x0a\x7a\
\x7f\x0a\x0a\x7c\xe2\x24\x1b\x58\xf6\xe9\xf2\x85\x00\x00\x00\x00\
\xa0\x02\xfa\xf0\x5f\xac\x00\x00\x02\x04\x05\xb4\x04\x02\x08\x0a\
\x4a\x43\x93\x29\x00\x00\x00\x00\x01\x03\x03\x07";
static const char *const kTcpOptionNames[] = {
[0] = "End of Option List",
[1] = "No-Operation",
[2] = "Maximum Segment Size",
[3] = "Window Scale",
[4] = "SACK Permitted",
[5] = "SACK",
[6] = "Echo (obsoleted by option 8)",
[7] = "Echo Reply (obsoleted by option 8)",
[8] = "Timestamps",
[9] = "Partial Order Connection Permitted (obsolete)",
[10] = "Partial Order Service Profile (obsolete)",
[11] = "CC (obsolete)",
[12] = "CC.NEW (obsolete)",
[13] = "CC.ECHO (obsolete)",
[14] = "TCP Alternate Checksum Request (obsolete)",
[15] = "TCP Alternate Checksum Data (obsolete)",
[16] = "Skeeter",
[17] = "Bubba",
[18] = "Trailer Checksum Option",
[19] = "MD5 Signature Option (obsoleted by option 29)",
[20] = "SCPS Capabilities",
[21] = "Selective Negative Acknowledgements",
[22] = "Record Boundaries",
[23] = "Corruption experienced",
[24] = "SNAP",
[25] = "Unassigned (released 2000-12-18)",
[26] = "TCP Compression Filter",
[27] = "Quick-Start Response",
[28] = "User Timeout Option",
[29] = "TCP Authentication Option (TCP-AO)",
[30] = "Multipath TCP (MPTCP)",
[31] = "Reserved (known unauthorized use without proper IANA assignm",
[32] = "Reserved (known unauthorized use without proper IANA assignm",
[33] = "Reserved (known unauthorized use without proper IANA assignm",
[34] = "variable TCP Fast Open Cookie",
[35] = "Reserved",
[69] = "Encryption Negotiation",
[253] = "RFC3692-1",
[254] = "RFC3692-2",
};
int main(int argc, char *argv[]) {
int version = (ip[0] & 0b11110000) >> 4;
int ihl = (ip[0] & 0b00001111) >> 0;
int dscp = (ip[1] & 0b11111100) >> 2;
int ecn = (ip[1] & 0b00000011) >> 0;
int lengthtotal = READ16BE(ip + 2);
int identification = READ16BE(ip + 4);
int flags = (ip[6] & 0b11100000) >> 5;
int fragmentoffset = (ip[6] & 0b00011111) << 8 | (ip[7] & 255);
int ttl = ip[8] & 255;
int protocol = ip[9] & 255;
int ipchecksum = (ip[10] & 255) << 8 | (ip[11] & 255);
int srcip = READ32BE(ip + 12);
int dstip = READ32BE(ip + 16);
printf("\n");
printf("// version = %u\n", version);
printf("// ihl = %u\n", ihl * 4);
printf("// dscp = %u\n", dscp);
printf("// ecn = %u\n", ecn);
printf("// lengthtotal = %u\n", lengthtotal);
printf("// identification = %u\n", identification);
printf("// flags = %u\n", flags);
printf("// fragmentoffset = %u\n", fragmentoffset);
printf("// ttl = %u\n", ttl);
printf("// protocol = %u\n", protocol);
printf("// ipchecksum = %u\n", ipchecksum);
printf("// srcip = %hhu.%hhu.%hhu.%hhu\n", srcip >> 24, srcip >> 16, srcip >> 8, srcip);
printf("// dstip = %hhu.%hhu.%hhu.%hhu\n", dstip >> 24, dstip >> 16, dstip >> 8, dstip);
printf("// \n");
char *tcp = ip + ihl * 4;
int srcport = READ16BE(tcp + 0);
int dstport = READ16BE(tcp + 2);
int sequence = READ32BE(tcp + 4);
int acknumber = READ32BE(tcp + 8);
int dataoffset = (tcp[12] & 0b11110000) >> 4;
bool ns = !!(tcp[12] & 0b00000001);
bool cwr = !!(tcp[13] & 0b10000000);
bool ece = !!(tcp[13] & 0b01000000);
bool urg = !!(tcp[13] & 0b00100000);
bool ack = !!(tcp[13] & 0b00010000);
bool psh = !!(tcp[13] & 0b00001000);
bool rst = !!(tcp[13] & 0b00000100);
bool syn = !!(tcp[13] & 0b00000010);
bool fin = !!(tcp[13] & 0b00000001);
int wsize = READ16BE(tcp + 14);
int tcpchecksum = READ16BE(tcp + 16);
int urgpointer = READ16BE(tcp + 18);
printf("// srcport = %u\n", srcport);
printf("// dstport = %u\n", dstport);
printf("// sequence = %u\n", sequence);
printf("// acknumber = %u\n", acknumber);
printf("// dataoffset = %u\n", dataoffset);
printf("// ns = %u\n", ns);
printf("// cwr = %u\n", cwr);
printf("// ece = %u\n", ece);
printf("// urg = %u\n", urg);
printf("// ack = %u\n", ack);
printf("// psh = %u\n", psh);
printf("// rst = %u\n", rst);
printf("// syn = %u\n", syn);
printf("// fin = %u\n", fin);
printf("// wsize = %u\n", wsize);
printf("// tcpchecksum = %u\n", tcpchecksum);
printf("// urgpointer = %u\n", urgpointer);
printf("// \n");
int c, i, j, n;
for (i = 20; i + 1 < dataoffset * 4;) {
printf("// option");
switch ((c = tcp[i] & 255)) {
case 0:
case 1:
printf(" %u", c);
++i;
break;
default:
n = tcp[i + 1] & 255;
printf(" %u %u", c, n);
for (j = 2; j < n; ++j) {
printf(" %u", tcp[i + j] & 255);
}
i += n;
break;
}
if (kTcpOptionNames[c]) {
printf(" (%s)", kTcpOptionNames[c]);
}
printf("\n");
}
return 0;
}

View file

@ -1,91 +0,0 @@
/*-*- 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
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/str/unicode.h"
#include "libc/fmt/fmt.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/x/xasprintf.h"
int a, b, w, i;
char name[512];
void DisplayUnicodeCharacter(void) {
int c, cw;
c = i;
cw = wcwidth(c);
if (cw < 1) {
c = '?';
cw = 1;
}
if (w) {
if (w + 1 + cw > 80) {
printf("\n");
w = 0;
} else {
fputc(' ', stdout);
w += 1 + cw;
}
}
if (!w) {
printf("%08x ", i);
w = 9 + cw;
}
fputwc(c, stdout);
}
void DisplayUnicodeBlock(void) {
if (a == 0x10000) {
printf("\n\n\n\n\n\n\n "
"ASTRAL PLANES\n\n\n\n\n");
}
if (a == 0x0590 /* hebrew */) return;
if (a == 0x0600 /* arabic */) return;
if (a == 0x08a0 /* arabic */) return;
if (a == 0x0750 /* arabic */) return;
if (a == 0x0700 /* syriac */) return;
if (a == 0x10800 /* cypriot */) return;
printf("\n\n%-60s%20s\n"
"──────────────────────────────────────────────"
"──────────────────────────────────\n",
name, _gc(xasprintf("%04x .. %04x", a, b)));
w = 0;
for (i = a; i <= b; ++i) {
DisplayUnicodeCharacter();
}
}
int main(int argc, char *argv[]) {
FILE *f;
char *line;
size_t linesize;
printf("\n\n\n\n\n UNICODE PLANES\n\n\n\n");
f = fopen("libc/str/blocks.txt", "r");
line = NULL;
linesize = 0;
while (!feof(f)) {
if (getline(&line, &linesize, f) == -1) break;
if (sscanf(line, "%x..%x; %s", &a, &b, name) != 3) continue;
DisplayUnicodeBlock();
}
free(line);
fclose(f);
return 0;
}

View file

@ -1,212 +0,0 @@
/*-*- 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
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/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/x/x.h"
#include "third_party/stb/stb_image.h"
#define C13(A, B) (((A) + 3 * (B)) / 4)
#define S3T(A, B, C) MAX(0, ((24 * (B)) - (4 * ((A) + (C)))) / 16)
#define LERP(A, B, P) ((A) * (1 - (P)) + (B) * (P))
float ByteToFloat(int b) {
return 1 / 255.f * b;
}
int FloatToByte(float f) {
return MAX(0, MIN(255, roundf(255 * f)));
}
float ChessBoard(unsigned y, unsigned x, float a, float b) {
return !((y ^ x) & (1u << 2)) ? a : b;
}
float AlphaBackground(unsigned y, unsigned x) {
return ChessBoard(y, x, 1.f, .7f);
}
float OutOfBoundsBackground(unsigned y, unsigned x) {
return ChessBoard(y, x, .01f, .02f);
}
float Opacify(size_t yn, size_t xn, const float P[yn][xn],
const float A[yn][xn], long y, long x) {
if ((0 <= y && y < yn) && (0 <= x && x < xn)) {
return LERP(AlphaBackground(y, x), P[y][x], A[y][x]);
} else {
return OutOfBoundsBackground(y, x);
}
}
void PrintImage(size_t yn, size_t xn, float R[yn][xn], float G[yn][xn],
float B[yn][xn], float A[yn][xn]) {
unsigned y, x;
for (y = 0; y < yn; y += 2) {
if (y) printf("\e[0m\n");
for (x = 0; x < xn; ++x) {
printf("\e[48;2;%d;%d;%d;38;2;%d;%d;%dm▄",
FloatToByte(Opacify(yn, xn, R, A, y + 0, x)),
FloatToByte(Opacify(yn, xn, G, A, y + 0, x)),
FloatToByte(Opacify(yn, xn, B, A, y + 0, x)),
FloatToByte(Opacify(yn, xn, R, A, y + 1, x)),
FloatToByte(Opacify(yn, xn, G, A, y + 1, x)),
FloatToByte(Opacify(yn, xn, B, A, y + 1, x)));
}
}
printf("\e[0m\n");
}
void DeblinterlaceRgba(size_t dyn, size_t dxn, float R[dyn][dxn],
float G[dyn][dxn], float B[dyn][dxn], float A[dyn][dxn],
size_t syn, size_t sxn,
const unsigned char src[syn][sxn][4]) {
unsigned y, x;
for (y = 0; y < syn; ++y) {
for (x = 0; x < sxn; ++x) {
R[y][x] = ByteToFloat(src[y][x][0]);
G[y][x] = ByteToFloat(src[y][x][1]);
B[y][x] = ByteToFloat(src[y][x][2]);
A[y][x] = ByteToFloat(src[y][x][3]);
}
}
}
void SharpenX(size_t yw, size_t xw, float dst[yw][xw], const float src[yw][xw],
size_t yn, size_t xn) {
int y, x;
for (y = 0; y < yn; ++y) {
for (x = 0; x < xn; ++x) {
dst[y][x] =
S3T(src[y][MAX(0, x - 1)], src[y][x], src[y][MIN(xn - 1, x + 1)]);
}
}
}
void SharpenY(size_t yw, size_t xw, float dst[yw][xw], const float src[yw][xw],
size_t yn, size_t xn) {
int y, x;
for (y = 0; y < yn; ++y) {
for (x = 0; x < xn; ++x) {
dst[y][x] =
S3T(src[MAX(0, y - 1)][x], src[y][x], src[MIN(yn - 1, y + 1)][x]);
}
}
}
void UpscaleX(size_t yw, size_t xw, float img[yw][xw], size_t yn, size_t xn) {
unsigned y, x;
for (y = yn; y--;) {
for (x = xn; --x;) {
img[y][x] =
C13(img[y][MIN(xn / 2 - 1, x / 2 - 1 + x % 2 * 2)], img[y][x / 2]);
}
}
}
void UpscaleY(size_t yw, size_t xw, float img[yw][xw], size_t yn, size_t xn) {
unsigned y, x;
for (y = yn; --y;) {
for (x = xn; x--;) {
img[y][x] =
C13(img[MIN(yn / 2 - 1, y / 2 - 1 + y % 2 * 2)][x], img[y / 2][x]);
}
}
}
void Upscale(size_t yw, size_t xw, float img[yw][xw], float tmp[yw][xw],
size_t yn, size_t xn) {
UpscaleY(yw, xw, img, yn, xn / 2);
SharpenY(yw, xw, tmp, img, yn, xn / 2);
UpscaleX(yw, xw, tmp, yn, xn);
SharpenX(yw, xw, img, tmp, yn, xn);
}
void ProcessImageDouble(size_t yn, size_t xn, unsigned char img[yn][xn][4]) {
void *t = xmemalign(32, sizeof(float) * yn * 2 * xn * 2);
void *R = xmemalign(32, sizeof(float) * yn * 2 * xn * 2);
void *G = xmemalign(32, sizeof(float) * yn * 2 * xn * 2);
void *B = xmemalign(32, sizeof(float) * yn * 2 * xn * 2);
void *A = xmemalign(32, sizeof(float) * yn * 2 * xn * 2);
DeblinterlaceRgba(yn * 2, xn * 2, R, G, B, A, yn, xn, img);
Upscale(yn * 2, xn * 2, R, t, yn * 2, xn * 2);
Upscale(yn * 2, xn * 2, G, t, yn * 2, xn * 2);
Upscale(yn * 2, xn * 2, B, t, yn * 2, xn * 2);
Upscale(yn * 2, xn * 2, A, t, yn * 2, xn * 2);
free(t);
PrintImage(yn * 2, xn * 2, R, G, B, A);
free(R);
free(G);
free(B);
free(A);
}
void ProcessImage(size_t yn, size_t xn, unsigned char img[yn][xn][4]) {
void *R = xmemalign(32, sizeof(float) * yn * xn);
void *G = xmemalign(32, sizeof(float) * yn * xn);
void *B = xmemalign(32, sizeof(float) * yn * xn);
void *A = xmemalign(32, sizeof(float) * yn * xn);
DeblinterlaceRgba(yn, xn, R, G, B, A, yn, xn, img);
PrintImage(yn, xn, R, G, B, A);
free(R);
free(G);
free(B);
free(A);
}
void WithImageFile(const char *path, void fn(size_t yn, size_t xn,
unsigned char img[yn][xn][4])) {
struct stat st;
int fd, yn, xn;
void *map, *data;
CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path);
CHECK_NE(-1, fstat(fd, &st));
CHECK_GT(st.st_size, 0);
CHECK_LE(st.st_size, INT_MAX);
fadvise(fd, 0, 0, MADV_WILLNEED | MADV_SEQUENTIAL);
CHECK_NE(MAP_FAILED,
(map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
CHECK_NOTNULL(
(data = stbi_load_from_memory(map, st.st_size, &xn, &yn, NULL, 4)), "%s",
path);
CHECK_NE(-1, munmap(map, st.st_size));
CHECK_NE(-1, close(fd));
fn(yn, xn, data);
free(data);
}
int main(int argc, char *argv[]) {
int i;
for (i = 1; i < argc; ++i) {
WithImageFile(argv[i], ProcessImageDouble);
}
return 0;
}

View file

@ -1,209 +0,0 @@
/*-*- 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
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/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/limits.h"
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/x/x.h"
#include "third_party/stb/stb_image.h"
#define CLAMP(X) MAX(0, MIN(255, X))
#define C13(A, B) (((A) + 3 * (B) + 2) >> 2)
#define S3T(A, B, C) CLAMP(-((A) >> 2) + ((B) + ((B) >> 1)) + -((C) >> 2))
#define LERP(X, Y, P) ((X) + (((P) * ((Y) - (X))) >> 8))
static unsigned char ChessBoard(unsigned y, unsigned x, unsigned char a,
unsigned char b) {
return !((y ^ x) & (1u << 2)) ? a : b;
}
static unsigned char AlphaBackground(unsigned y, unsigned x) {
return ChessBoard(y, x, 255, 200);
}
static unsigned char OutOfBoundsBackground(unsigned y, unsigned x) {
return ChessBoard(y, x, 40, 80);
}
static unsigned char Opacify(size_t yn, size_t xn,
const unsigned char P[yn][xn],
const unsigned char A[yn][xn], long y, long x) {
if ((0 <= y && y < yn) && (0 <= x && x < xn)) {
return LERP(AlphaBackground(y, x), P[y][x], A[y][x]);
} else {
return OutOfBoundsBackground(y, x);
}
}
static void PrintImage(size_t yn, size_t xn, unsigned char R[yn][xn],
unsigned char G[yn][xn], unsigned char B[yn][xn],
unsigned char A[yn][xn]) {
unsigned y, x;
for (y = 0; y < yn; y += 2) {
if (y) printf("\e[0m\n");
for (x = 0; x < xn; ++x) {
printf("\e[48;2;%d;%d;%d;38;2;%d;%d;%dm▄",
Opacify(yn, xn, R, A, y + 0, x), Opacify(yn, xn, G, A, y + 0, x),
Opacify(yn, xn, B, A, y + 0, x), Opacify(yn, xn, R, A, y + 1, x),
Opacify(yn, xn, G, A, y + 1, x), Opacify(yn, xn, B, A, y + 1, x));
}
}
printf("\e[0m\n");
}
static void DeblinterlaceRgba(size_t dyn, size_t dxn, unsigned char R[dyn][dxn],
unsigned char G[dyn][dxn],
unsigned char B[dyn][dxn],
unsigned char A[dyn][dxn], size_t syn, size_t sxn,
const unsigned char src[syn][sxn][4]) {
unsigned y, x;
for (y = 0; y < syn; ++y) {
for (x = 0; x < sxn; ++x) {
R[y][x] = src[y][x][0];
G[y][x] = src[y][x][1];
B[y][x] = src[y][x][2];
A[y][x] = src[y][x][3];
}
}
}
static void SharpenX(size_t yw, size_t xw, unsigned char dst[yw][xw],
const unsigned char src[yw][xw], size_t yn, size_t xn) {
int y, x;
for (y = 0; y < yn; ++y) {
for (x = 0; x < xn; ++x) {
dst[y][x] =
S3T(src[y][MAX(0, x - 1)], src[y][x], src[y][MIN(xn - 1, x + 1)]);
}
}
}
static void SharpenY(size_t yw, size_t xw, unsigned char dst[yw][xw],
const unsigned char src[yw][xw], size_t yn, size_t xn) {
int y, x;
for (y = 0; y < yn; ++y) {
for (x = 0; x < xn; ++x) {
dst[y][x] =
S3T(src[MAX(0, y - 1)][x], src[y][x], src[MIN(yn - 1, y + 1)][x]);
}
}
}
static void UpscaleX(size_t yw, size_t xw, unsigned char img[yw][xw], size_t yn,
size_t xn) {
unsigned y, x;
for (y = yn; y--;) {
for (x = xn; --x;) {
img[y][x] =
C13(img[y][MIN(xn / 2 - 1, x / 2 - 1 + x % 2 * 2)], img[y][x / 2]);
}
}
}
static void UpscaleY(size_t yw, size_t xw, unsigned char img[yw][xw], size_t yn,
size_t xn) {
unsigned y, x;
for (y = yn; --y;) {
for (x = xn; x--;) {
img[y][x] =
C13(img[MIN(yn / 2 - 1, y / 2 - 1 + y % 2 * 2)][x], img[y / 2][x]);
}
}
}
static void Upscale(size_t yw, size_t xw, unsigned char img[yw][xw],
unsigned char tmp[yw][xw], size_t yn, size_t xn) {
UpscaleY(yw, xw, img, yn, xn / 2);
SharpenY(yw, xw, tmp, img, yn, xn / 2);
UpscaleX(yw, xw, tmp, yn, xn);
SharpenX(yw, xw, img, tmp, yn, xn);
}
static void ProcessImageDouble(size_t yn, size_t xn,
unsigned char img[yn][xn][4]) {
void *t = xmemalign(32, sizeof(unsigned char) * yn * 2 * xn * 2);
void *R = xmemalign(32, sizeof(unsigned char) * yn * 2 * xn * 2);
void *G = xmemalign(32, sizeof(unsigned char) * yn * 2 * xn * 2);
void *B = xmemalign(32, sizeof(unsigned char) * yn * 2 * xn * 2);
void *A = xmemalign(32, sizeof(unsigned char) * yn * 2 * xn * 2);
DeblinterlaceRgba(yn * 2, xn * 2, R, G, B, A, yn, xn, img);
Upscale(yn * 2, xn * 2, R, t, yn * 2, xn * 2);
Upscale(yn * 2, xn * 2, G, t, yn * 2, xn * 2);
Upscale(yn * 2, xn * 2, B, t, yn * 2, xn * 2);
Upscale(yn * 2, xn * 2, A, t, yn * 2, xn * 2);
free(t);
PrintImage(yn * 2, xn * 2, R, G, B, A);
free(R);
free(G);
free(B);
free(A);
}
static void ProcessImage(size_t yn, size_t xn, unsigned char img[yn][xn][4]) {
void *R = xmemalign(32, sizeof(unsigned char) * yn * xn);
void *G = xmemalign(32, sizeof(unsigned char) * yn * xn);
void *B = xmemalign(32, sizeof(unsigned char) * yn * xn);
void *A = xmemalign(32, sizeof(unsigned char) * yn * xn);
DeblinterlaceRgba(yn, xn, R, G, B, A, yn, xn, img);
PrintImage(yn, xn, R, G, B, A);
free(R);
free(G);
free(B);
free(A);
}
void WithImageFile(const char *path, void fn(size_t yn, size_t xn,
unsigned char img[yn][xn][4])) {
struct stat st;
int fd, yn, xn;
void *map, *data;
CHECK_NE(-1, (fd = open(path, O_RDONLY)), "%s", path);
CHECK_NE(-1, fstat(fd, &st));
CHECK_GT(st.st_size, 0);
CHECK_LE(st.st_size, INT_MAX);
fadvise(fd, 0, 0, MADV_WILLNEED | MADV_SEQUENTIAL);
CHECK_NE(MAP_FAILED,
(map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)));
CHECK_NOTNULL(
(data = stbi_load_from_memory(map, st.st_size, &xn, &yn, NULL, 4)), "%s",
path);
CHECK_NE(-1, munmap(map, st.st_size));
CHECK_NE(-1, close(fd));
fn(yn, xn, data);
free(data);
}
int main(int argc, char *argv[]) {
int i;
for (i = 1; i < argc; ++i) {
WithImageFile(argv[i], ProcessImageDouble);
}
return 0;
}

View file

@ -1,85 +0,0 @@
/*-*- 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 2022 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/struct/sigaction.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/ucontext.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/auxv.h"
#include "libc/sysv/consts/sa.h"
#include "libc/sysv/consts/sig.h"
#include "third_party/xed/x86.h"
#ifdef __x86_64__
#define OUTPATH "vdso.elf"
volatile bool finished;
void OnSegmentationFault(int sig, siginfo_t *si, void *vctx) {
struct XedDecodedInst xedd;
ucontext_t *ctx = vctx;
xed_decoded_inst_zero_set_mode(&xedd, XED_MACHINE_MODE_LONG_64);
xed_instruction_length_decode(&xedd, (void *)ctx->uc_mcontext.rip, 15);
ctx->uc_mcontext.rip += xedd.length;
finished = true;
}
int main(int argc, char *argv[]) {
FILE *f;
int byte;
volatile unsigned char *vdso, *p;
vdso = (unsigned char *)getauxval(AT_SYSINFO_EHDR);
if (vdso) {
fprintf(stderr, "vdso found at address %p\n", vdso);
} else {
fprintf(stderr, "error: AT_SYSINFO_EHDR was not in auxiliary values\n");
return 1;
}
f = fopen(OUTPATH, "wb");
if (!f) {
fprintf(stderr, "error: fopen(%`'s) failed\n", OUTPATH);
return 1;
}
struct sigaction sa = {
.sa_sigaction = OnSegmentationFault,
.sa_flags = SA_SIGINFO,
};
sigaction(SIGSEGV, &sa, 0);
sigaction(SIGBUS, &sa, 0);
p = vdso;
for (;;) {
byte = *p++;
if (!finished) {
fputc(byte, f);
} else {
break;
}
}
fclose(f);
fprintf(stderr, "%zu bytes dumped to %s\n", p - vdso, OUTPATH);
return 0;
}
#endif /* __x86_64__ */

View file

@ -1,166 +0,0 @@
/*-*- 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 2022 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/elf/def.h"
#include "libc/elf/scalar.h"
#include "libc/elf/struct/ehdr.h"
#include "libc/elf/struct/phdr.h"
#include "libc/elf/struct/sym.h"
#include "libc/elf/struct/verdaux.h"
#include "libc/elf/struct/verdef.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/auxv.h"
static inline void PrintDsoSymbolVersions(Elf64_Verdef *vd, int sym,
char *strtab) {
Elf64_Verdaux *aux;
for (;; vd = (Elf64_Verdef *)((char *)vd + vd->vd_next)) {
if (!(vd->vd_flags & VER_FLG_BASE) &&
(vd->vd_ndx & 0x7fff) == (sym & 0x7fff)) {
aux = (Elf64_Verdaux *)((char *)vd + vd->vd_aux);
kprintf(" %s", strtab + aux->vda_name);
}
if (!vd->vd_next) {
break;
}
}
}
int PrintVdsoSymbols(void) {
void *p;
size_t i;
Elf64_Ehdr *ehdr;
Elf64_Phdr *phdr;
char *strtab = 0;
size_t *dyn, base;
unsigned long *ap;
Elf64_Sym *symtab = 0;
uint16_t *versym = 0;
Elf_Symndx *hashtab = 0;
Elf64_Verdef *verdef = 0;
const char *typename, *bindname;
for (ehdr = 0, ap = __auxv; ap[0]; ap += 2) {
if (ap[0] == AT_SYSINFO_EHDR) {
ehdr = (void *)ap[1];
break;
}
}
if (!ehdr) {
kprintf("error: AT_SYSINFO_EHDR not found\n");
return 1;
}
phdr = (void *)((char *)ehdr + ehdr->e_phoff);
for (base = -1, dyn = 0, i = 0; i < ehdr->e_phnum;
i++, phdr = (void *)((char *)phdr + ehdr->e_phentsize)) {
switch (phdr->p_type) {
case PT_LOAD:
// modern linux uses the base address zero, but elders
// e.g. rhel7 uses the base address 0xffffffffff700000
base = (size_t)ehdr + phdr->p_offset - phdr->p_vaddr;
break;
case PT_DYNAMIC:
dyn = (void *)((char *)ehdr + phdr->p_offset);
break;
default:
break;
}
}
if (!dyn || base == -1) {
kprintf("error: missing program headers\n");
return 2;
}
for (i = 0; dyn[i]; i += 2) {
p = (void *)(base + dyn[i + 1]);
switch (dyn[i]) {
case DT_STRTAB:
strtab = p;
break;
case DT_SYMTAB:
symtab = p;
break;
case DT_HASH:
hashtab = p;
break;
case DT_VERSYM:
versym = p;
break;
case DT_VERDEF:
verdef = p;
break;
}
}
if (!verdef) {
versym = 0;
}
if (!strtab || !symtab || !hashtab) {
kprintf("error: strtab/symtab/hashtab not found\n");
return 3;
}
for (i = 0; i < hashtab[1]; i++) {
if (!symtab[i].st_shndx) {
continue;
}
switch (ELF64_ST_BIND(symtab[i].st_info)) {
case STB_LOCAL:
bindname = "locl";
break;
case STB_GLOBAL:
bindname = "glob";
break;
case STB_WEAK:
bindname = "weak";
break;
default:
bindname = "????";
break;
}
switch (ELF64_ST_TYPE(symtab[i].st_info)) {
case STT_FUNC:
typename = "func";
break;
case STT_OBJECT:
typename = " obj";
break;
case STT_NOTYPE:
typename = "none";
break;
default:
typename = "????";
break;
}
kprintf("%s %s %-40s", bindname, typename, strtab + symtab[i].st_name);
PrintDsoSymbolVersions(verdef, versym[i], strtab);
kprintf("\n");
}
return 0;
}
int main(int argc, char *argv[]) {
return PrintVdsoSymbols();
}

View file

@ -1,97 +0,0 @@
/*-*- 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
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/assert.h"
#include "libc/stdio/stdio.h"
#define DIST(X, Y) ((X) - (Y))
#define SQR(X) ((X) * (X))
#define SUM(X, Y, Z) ((X) + (Y) + (Z))
static const uint8_t kXtermCube[] = {0, 0137, 0207, 0257, 0327, 0377};
static int uncube(int x) {
return x < 48 ? 0 : x < 115 ? 1 : (x - 35) / 40;
}
static int rgb2xterm256(int r, int g, int b) {
unsigned av, ir, ig, ib, il, qr, qg, qb, ql;
av = (r + g + b) / 3;
ql = (il = av > 238 ? 23 : (av - 3) / 10) * 10 + 8;
qr = kXtermCube[(ir = uncube(r))];
qg = kXtermCube[(ig = uncube(g))];
qb = kXtermCube[(ib = uncube(b))];
if (SUM(SQR(DIST(qr, r)), SQR(DIST(qg, g)), SQR(DIST(qb, b))) <=
SUM(SQR(DIST(ql, r)), SQR(DIST(ql, g)), SQR(DIST(ql, b)))) {
return ir * 36 + ig * 6 + ib + 020;
} else {
return il + 0350;
}
}
bool IsUglyColorMixture(int rune, int y, int tone, bool toneisfg) {
assert(tone == 16 || (231 <= tone && tone <= 255));
return false;
}
int main(int argc, char *argv[]) {
unsigned y, z, x, k, w;
static const char16_t s[2][3] = {{u'', u'', u''}, {u'', u'', u''}};
printf("\npure\n");
for (y = 0; y < 6; ++y) {
for (z = 0; z < 6; ++z) {
for (x = 0; x < 6; ++x) {
printf("\033[48;5;%hhum ", 16 + x + y * 6 + z * 6 * 6);
}
printf("\033[0m ");
}
printf("\n");
}
#define MIX(NAME, COLOR) \
do { \
printf("\n%s %d ▓░/▒▒/░▓\n", NAME, COLOR); \
for (k = 0; k < 3; ++k) { \
for (y = 0; y < 6; ++y) { \
for (z = 0; z < 6; ++z) { \
for (x = 0; x < 6; ++x) { \
printf("\033[48;5;%hhu;38;5;%hhum%lc", COLOR, \
16 + x + y * 6 + z * 6 * 6, s[0][k]); \
printf("\033[48;5;%hhu;38;5;%hhum%lc", 16 + x + y * 6 + z * 6 * 6, \
COLOR, s[1][k]); \
} \
printf("\033[0m "); \
} \
printf("\n"); \
} \
} \
} while (0)
MIX("tint", 231);
MIX("tint", 255);
MIX("tint", 254);
MIX("tone", 240);
MIX("shade", 232);
for (w = 233; w < 254; ++w) {
MIX("gray", w);
}
return 0;
}

View file

@ -1,183 +0,0 @@
/*-*- 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
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 "dsp/tty/quant.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/xchg.internal.h"
#include "libc/math.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
/* #define ROUND(x) x */
/* #define RT int */
/* #define R1 1 */
/* #define R2 2 */
/* #define R3 3 */
#define RT float
#define MUL(x, y) ((x) * (y))
#define RND(x) roundf(x)
#define R1 0.25f
#define R2 0.50f
#define R3 0.75f
#define rgb_t struct TtyRgb
forceinline RT lerp(RT x, RT y, RT d) {
return x * (1.0 - d) + y * d;
}
forceinline int lerp255(RT x, RT y, RT d) {
return lerp(x / 255.0, y / 255.0, d) * 255.0;
}
forceinline rgb_t rgblerp(rgb_t x, rgb_t y, RT d) {
return (rgb_t){lerp255(x.r, y.r, d), lerp255(x.g, y.g, d),
lerp255(x.b, y.b, d)};
}
forceinline rgb_t getquant(unsigned xt) {
return g_ansi2rgb_[xt];
}
forceinline unsigned dist(int x, int y) {
return x - y;
}
forceinline unsigned sqr(int x) {
return x * x;
}
forceinline unsigned rgbdist(rgb_t x, rgb_t y) {
return sqrt(sqr(dist(x.r, y.r)) + sqr(dist(x.g, y.g)) + sqr(dist(x.b, y.b)));
}
bool b;
rgb_t rgb, cc, c1, c2;
unsigned i, j, k, m, n, x, y;
char buf[128];
/* 0125 025 067-29 # '░' bg=0352 fg=0306 → ░░░ */
/* 0125 025 067-29 # '▓' bg=0306 fg=0352 → ▓▓▓ */
/* 0125 055 067-29 # '░' bg=0352 fg=0314 → ░░░ */
int main(int argc, char *argv[]) {
/* memcpy(g_ansi2rgb_, &kTangoPalette, sizeof(kTangoPalette)); */
/* i = 21; */
/* j = 22; */
/* c1 = getquant(i); */
/* c2 = getquant(j); */
/* cc = rgblerp(c1, c2, R1); */
/* printf("rgblerp((%3d,%3d,%3d), (%3d,%3d,%3d),4) → (%3d,%3d,%3d)\n", c1.r,
*/
/* c1.g, c1.b, c2.r, c2.g, c2.b, cc.r, cc.g, cc.b); */
/* exit(0); */
for (m = 16; m < 256; m += 6) {
for (n = 16; n < 256; n += 6) {
printf("------------------------------------------------------------\n");
i = m;
j = n;
b = false;
while (i < m + 6) {
printf("\n");
cc = getquant(i);
sprintf(buf, "\e[48;5;%dm ", i);
printf("0x%02x%02x%02x, %d,%d,0\t/* 0x%02x%02x%02x "
" + ' ' bg=%3d → %s \e[0m */\n",
cc.b, cc.g, cc.r, i, 0, getquant(i).r, getquant(i).g,
getquant(i).b, i, buf);
#if 0
sprintf(buf, "\e[38;5;%dm███", i);
printf("0x%08x 0x%02x%02x%02x\t"
" '█' fg=%3d → %s\e[0m\n",
cc.b, cc.g, cc.r, strlen(buf), i, buf);
#endif
for (x = i; x < i + 1; ++x) {
for (y = j; y < j + 1; ++y) {
for (k = 0; k < 2; ++k) {
if (x > y /* && */
/* rgbdist(getquant(x), getquant(y)) < 49744125 / 16 */ /* &&
((32
<= x && x <= 232) && (32 <= y && y <= 232))
&& */
/* (cc.r > 0137 && cc.g > 0137 && cc.b > 0137) */) {
sprintf(buf, "\e[48;5;%d;38;5;%dm░░░", x, y);
cc = rgblerp(getquant(x), getquant(y), R1);
printf("0x%02x%02x%02x, %d,%d,1\t/* 0x%02x%02x%02x + "
"0x%02x%02x%02x"
" + '░' bg=%3d fg=%3d → "
"\e[48;5;%dm \e[48;5;%dm "
"%s\e[48;2;%d;%d;%dm \e[0m */\n",
cc.b, cc.g, cc.r, x, y, getquant(x).r, getquant(x).g,
getquant(x).b, getquant(y).r, getquant(y).g,
getquant(y).b, x, y, x, y, buf, cc.r, cc.g, cc.b);
sprintf(buf, "\e[48;5;%d;38;5;%dm▒▒▒", x, y);
cc = rgblerp(getquant(x), getquant(y), R2);
printf("0x%02x%02x%02x, %d,%d,2\t/* 0x%02x%02x%02x + "
"0x%02x%02x%02x"
" + '▒' bg=%3d fg=%3d → "
"\e[48;5;%dm \e[48;5;%dm "
"%s\e[48;2;%d;%d;%dm \e[0m */\n",
cc.b, cc.g, cc.r, x, y, getquant(x).r, getquant(x).g,
getquant(x).b, getquant(y).r, getquant(y).g,
getquant(y).b, x, y, x, y, buf, cc.r, cc.g, cc.b);
sprintf(buf, "\e[48;5;%d;38;5;%dm▓▓▓", x, y);
cc = rgblerp(getquant(x), getquant(y), R3);
printf("0x%02x%02x%02x, %d,%d,3\t/* 0x%02x%02x%02x + "
"0x%02x%02x%02x"
" + '▓' bg=%3d fg=%3d → "
"\e[48;5;%dm \e[48;5;%dm "
"%s\e[48;2;%d;%d;%dm \e[0m */\n",
cc.b, cc.g, cc.r, x, y, getquant(x).r, getquant(x).g,
getquant(x).b, getquant(y).r, getquant(y).g,
getquant(y).b, x, y, x, y, buf, cc.r, cc.g, cc.b);
}
#if 0
sprintf(buf, "\e[48;5;%d;38;5;%dm▓▓▓", x, y);
cc = rgblerp((c1 = getquant(x)), (c2 = getquant(y)), R3);
printf("0%03o%03o%03o\t# '▓' bg=%3d fg=%3d → "
"%s\e[48;2;%d;%d;%dm \e[0m\n",
cc.b, cc.g, cc.r, strlen(buf), x, y, buf,
lerp255(c1.r, c2.r, R3), lerp255(c1.g, c2.g, R3),
lerp255(c1.b, c2.b, R3));
#endif
xchg(&x, &y);
}
}
}
++i;
++j;
}
}
}
/* for (i = 0; i < 255; ++i) { */
/* for (j = 0; j < 255; ++j) { */
/* for (k = 0; k < 255; ++k) { */
/* printf("0%03o%03o%03o\n", i, j, k); */
/* } */
/* } */
/* } */
return 0;
}

View file

@ -1,186 +0,0 @@
/*-*- 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
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 "dsp/tty/quant.h"
#include "libc/fmt/fmt.h"
#include "libc/log/check.h"
#include "libc/macros.internal.h"
#include "libc/math.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/exit.h"
#include "third_party/getopt/getopt.internal.h"
#define USAGE \
" [FLAGS] [PATH...]\n\
\n\
Flags:\n\
-o PATH output path\n\
-h shows this information\n\
\n"
static size_t linecap_;
static FILE *in_, *out_;
static char *inpath_, *outpath_, *line_;
void PrintUsage(int rc, FILE *f) {
fputs("Usage: ", f);
fputs(program_invocation_name, f);
fputs(USAGE, f);
exit(rc);
}
void GetOpts(int *argc, char *argv[]) {
int opt;
outpath_ = "-";
while ((opt = getopt(*argc, argv, "?ho:")) != -1) {
switch (opt) {
case 'o':
outpath_ = optarg;
break;
case '?':
case 'h':
PrintUsage(EXIT_SUCCESS, stdout);
default:
PrintUsage(EX_USAGE, stderr);
}
}
if (optind == *argc) {
argv[(*argc)++] = "-";
}
}
#define U256F1(X) ((float)((X)&0xffu) * 256.0f)
#define F1U256(X) MAX(MIN((int)rintl(roundl(256.0f * (X))), 255), 0)
forceinline struct TtyRgb getquant(unsigned xt) {
return g_ansi2rgb_[xt];
}
forceinline unsigned dist(int x, int y) {
return x - y;
}
forceinline unsigned sqr(int x) {
return x * x;
}
static unsigned rgb2hsl(unsigned rgba) {
/* this is broken */
unsigned h8, s8, l8;
float r, g, b, h, s, d, l, cmax, cmin;
r = U256F1(rgba);
g = U256F1(rgba >> 010);
b = U256F1(rgba >> 020);
cmax = MAX(MAX(r, g), b);
cmin = MIN(MIN(r, g), b);
h = 0.0f;
s = 0.0f;
d = cmax - cmin;
l = (cmax + cmin) / 2.0f;
if (cmax != cmin) {
s = l > 0.5L ? d / (2.0f - cmax - cmin) : d / (cmax + cmin);
if (cmax == r) {
h = (g - b) / d + (g < b ? 6.0f : 0.0f);
} else if (cmax == g) {
h = (b - r) / d + 2.0f;
} else if (cmax == b) {
h = (r - g) / d + 4.0f;
}
h /= 6.0f;
}
h8 = F1U256(h);
s8 = F1U256(s);
l8 = F1U256(l);
return ((rgba >> 030) & 255) << 030 | l8 << 020 | s8 << 010 | h8;
}
static struct TtyRgb rgb2hsl2(struct TtyRgb rgb) {
unsigned x =
(unsigned)rgb.b << 020 | (unsigned)rgb.g << 010 | (unsigned)rgb.r;
unsigned y = rgb2hsl(x);
return (struct TtyRgb){
.r = y & 0xff, .g = (y >> 010) & 0xff, .b = (y >> 020) & 0xff};
}
static unsigned rgbdist(struct TtyRgb x, struct TtyRgb y) {
x = rgb2hsl2(x);
y = rgb2hsl2(y);
return sqrt(sqr(dist(x.r, y.r)) + sqr(dist(x.g, y.g)) + sqr(dist(x.b, y.b)));
}
static unsigned xtdist(unsigned x, unsigned y) {
return rgbdist(getquant(x), getquant(y));
}
void Show(unsigned color, unsigned bg, unsigned fg, unsigned glyph) {
uint8_t r, g, b;
b = (color >> 020) & 0xff;
g = (color >> 010) & 0xff;
r = color & 0xff;
printf("\tmix\t0x%04x,%3d,%3d,%3d,%3d,%3d,%3d\t# \e[48;2;%d;%d;%dm \e[0m\n",
rgbdist((struct TtyRgb){r, g, b, 0}, (struct TtyRgb){0, 0, 0, 0}), r,
g, b, bg, fg, glyph, r, g, b);
}
void ProcessFile(void) {
char *p;
unsigned color1, bg1, fg1, glyph1;
unsigned color, bg, fg, glyph;
color1 = -1u;
bg1 = -1u;
fg1 = -1u;
glyph1 = -1u;
while ((getline(&line_, &linecap_, in_)) != -1) {
p = _chomp(line_);
sscanf(p, "%x, %u,%u,%u", &color, &bg, &fg, &glyph);
if (color != color1) {
if (color1 != -1u) {
Show(color1, bg1, fg1, glyph1);
}
color1 = color;
bg1 = bg;
fg1 = fg;
glyph1 = glyph;
}
if ((fg1 && !fg) || (fg && fg1 && xtdist(fg, bg) < xtdist(fg1, bg1))) {
color1 = color;
bg1 = bg;
fg1 = fg;
glyph1 = glyph;
}
}
Show(color1, bg1, fg1, glyph1);
}
int main(int argc, char *argv[]) {
size_t i;
GetOpts(&argc, argv);
CHECK_NOTNULL((out_ = fopen(outpath_, "w")));
for (i = optind; i < argc; ++i) {
CHECK_NOTNULL((in_ = fopen((inpath_ = argv[i]), "r")));
ProcessFile();
CHECK_NE(-1, fclose(in_));
in_ = 0;
}
CHECK_NE(-1, fclose(out_));
out_ = 0;
free(line_);
return 0;
}

View file

@ -1,77 +0,0 @@
/*-*- 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/math.h"
#include "libc/stdio/stdio.h"
#define N 8
#define SQR(X) ((X) * (X))
static const uint8_t kXtermCube[6] = {0, 0137, 0207, 0257, 0327, 0377};
static int rgb2xterm256(int r, int g, int b) {
int cerr, gerr, ir, ig, ib, gray, grai, cr, cg, cb, gv;
gray = round(r * .299 + g * .587 + b * .114);
grai = gray > 238 ? 23 : (gray - 3) / 10;
ir = r < 48 ? 0 : r < 115 ? 1 : (r - 35) / 40;
ig = g < 48 ? 0 : g < 115 ? 1 : (g - 35) / 40;
ib = b < 48 ? 0 : b < 115 ? 1 : (b - 35) / 40;
cr = kXtermCube[ir];
cg = kXtermCube[ig];
cb = kXtermCube[ib];
gv = 8 + 10 * grai;
cerr = SQR(cr - r) + SQR(cg - g) + SQR(cb - b);
gerr = SQR(gv - r) + SQR(gv - g) + SQR(gv - b);
if (cerr <= gerr) {
return 16 + 36 * ir + 6 * ig + ib;
} else {
return 232 + grai;
}
}
int main(int argc, char *argv[]) {
double d;
int i, j, x;
int r, g, b;
double G[N][3];
double rgb[2][3] = {
{1, 0, 0},
{0, 1, 0},
};
for (i = 0; i < N; ++i) {
for (j = 0; j < 3; ++j) {
d = (rgb[1][j] - rgb[0][j]) / (N - 1);
G[i][j] = rgb[0][j] + d * i;
}
}
for (i = 0; i < N; ++i) {
r = round(G[i][0] * 255);
g = round(G[i][1] * 255);
b = round(G[i][2] * 255);
x = rgb2xterm256(r, g, b);
printf("\e[38;5;232;48;5;%dmabcdefg \e[0m %3d "
"\e[38;5;232;48;2;%d;%d;%dmabcdgefg \e[0m "
"%3d %3d %3d %f %f %f\n",
x, x, r, g, b, r, g, b, G[i][0], G[i][1], G[i][2]);
}
return 0;
}

View file

@ -1,706 +0,0 @@
/*-*- 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
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 "dsp/tty/xtermname.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
struct Rgb {
uint8_t r, g, b;
};
const struct Rgb kTango[16] = {
{0x00, 0x00, 0x00}, {0x80, 0x00, 0x00}, {0x00, 0x80, 0x00},
{0x80, 0x80, 0x00}, {0x00, 0x00, 0x80}, {0x80, 0x00, 0x80},
{0x00, 0x80, 0x80}, {0xc0, 0xc0, 0xc0}, {0x80, 0x80, 0x80},
{0xff, 0x00, 0x00}, {0x00, 0xff, 0x00}, {0xff, 0xff, 0x00},
{0x00, 0x00, 0xff}, {0xff, 0x00, 0xff}, {0x00, 0xff, 0xff},
{0xff, 0xff, 0xff},
};
const struct Rgb kXtermRgb[] = {
/* 0..15: ansi 16-color palette */
{0x00, 0x00, 0x00},
{0x80, 0x00, 0x00},
{0x00, 0x80, 0x00},
{0x80, 0x80, 0x00},
{0x00, 0x00, 0x80},
{0x80, 0x00, 0x80},
{0x00, 0x80, 0x80},
{0xc0, 0xc0, 0xc0},
{0x80, 0x80, 0x80},
{0xff, 0x00, 0x00},
{0x00, 0xff, 0x00},
{0xff, 0xff, 0x00},
{0x00, 0x00, 0xff},
{0xff, 0x00, 0xff},
{0x00, 0xff, 0xff},
{0xff, 0xff, 0xff},
/* 16..231: xterm256 color cubes */
{0x00, 0x00, 0x00},
{0x00, 0x00, 0x5f},
{0x00, 0x00, 0x87},
{0x00, 0x00, 0xaf},
{0x00, 0x00, 0xd7},
{0x00, 0x00, 0xff},
{0x00, 0x5f, 0x00},
{0x00, 0x5f, 0x5f},
{0x00, 0x5f, 0x87},
{0x00, 0x5f, 0xaf},
{0x00, 0x5f, 0xd7},
{0x00, 0x5f, 0xff},
{0x00, 0x87, 0x00},
{0x00, 0x87, 0x5f},
{0x00, 0x87, 0x87},
{0x00, 0x87, 0xaf},
{0x00, 0x87, 0xd7},
{0x00, 0x87, 0xff},
{0x00, 0xaf, 0x00},
{0x00, 0xaf, 0x5f},
{0x00, 0xaf, 0x87},
{0x00, 0xaf, 0xaf},
{0x00, 0xaf, 0xd7},
{0x00, 0xaf, 0xff},
{0x00, 0xd7, 0x00},
{0x00, 0xd7, 0x5f},
{0x00, 0xd7, 0x87},
{0x00, 0xd7, 0xaf},
{0x00, 0xd7, 0xd7},
{0x00, 0xd7, 0xff},
{0x00, 0xff, 0x00},
{0x00, 0xff, 0x5f},
{0x00, 0xff, 0x87},
{0x00, 0xff, 0xaf},
{0x00, 0xff, 0xd7},
{0x00, 0xff, 0xff},
{0x5f, 0x00, 0x00},
{0x5f, 0x00, 0x5f},
{0x5f, 0x00, 0x87},
{0x5f, 0x00, 0xaf},
{0x5f, 0x00, 0xd7},
{0x5f, 0x00, 0xff},
{0x5f, 0x5f, 0x00},
{0x5f, 0x5f, 0x5f},
{0x5f, 0x5f, 0x87},
{0x5f, 0x5f, 0xaf},
{0x5f, 0x5f, 0xd7},
{0x5f, 0x5f, 0xff},
{0x5f, 0x87, 0x00},
{0x5f, 0x87, 0x5f},
{0x5f, 0x87, 0x87},
{0x5f, 0x87, 0xaf},
{0x5f, 0x87, 0xd7},
{0x5f, 0x87, 0xff},
{0x5f, 0xaf, 0x00},
{0x5f, 0xaf, 0x5f},
{0x5f, 0xaf, 0x87},
{0x5f, 0xaf, 0xaf},
{0x5f, 0xaf, 0xd7},
{0x5f, 0xaf, 0xff},
{0x5f, 0xd7, 0x00},
{0x5f, 0xd7, 0x5f},
{0x5f, 0xd7, 0x87},
{0x5f, 0xd7, 0xaf},
{0x5f, 0xd7, 0xd7},
{0x5f, 0xd7, 0xff},
{0x5f, 0xff, 0x00},
{0x5f, 0xff, 0x5f},
{0x5f, 0xff, 0x87},
{0x5f, 0xff, 0xaf},
{0x5f, 0xff, 0xd7},
{0x5f, 0xff, 0xff},
{0x87, 0x00, 0x00},
{0x87, 0x00, 0x5f},
{0x87, 0x00, 0x87},
{0x87, 0x00, 0xaf},
{0x87, 0x00, 0xd7},
{0x87, 0x00, 0xff},
{0x87, 0x5f, 0x00},
{0x87, 0x5f, 0x5f},
{0x87, 0x5f, 0x87},
{0x87, 0x5f, 0xaf},
{0x87, 0x5f, 0xd7},
{0x87, 0x5f, 0xff},
{0x87, 0x87, 0x00},
{0x87, 0x87, 0x5f},
{0x87, 0x87, 0x87},
{0x87, 0x87, 0xaf},
{0x87, 0x87, 0xd7},
{0x87, 0x87, 0xff},
{0x87, 0xaf, 0x00},
{0x87, 0xaf, 0x5f},
{0x87, 0xaf, 0x87},
{0x87, 0xaf, 0xaf},
{0x87, 0xaf, 0xd7},
{0x87, 0xaf, 0xff},
{0x87, 0xd7, 0x00},
{0x87, 0xd7, 0x5f},
{0x87, 0xd7, 0x87},
{0x87, 0xd7, 0xaf},
{0x87, 0xd7, 0xd7},
{0x87, 0xd7, 0xff},
{0x87, 0xff, 0x00},
{0x87, 0xff, 0x5f},
{0x87, 0xff, 0x87},
{0x87, 0xff, 0xaf},
{0x87, 0xff, 0xd7},
{0x87, 0xff, 0xff},
{0xaf, 0x00, 0x00},
{0xaf, 0x00, 0x5f},
{0xaf, 0x00, 0x87},
{0xaf, 0x00, 0xaf},
{0xaf, 0x00, 0xd7},
{0xaf, 0x00, 0xff},
{0xaf, 0x5f, 0x00},
{0xaf, 0x5f, 0x5f},
{0xaf, 0x5f, 0x87},
{0xaf, 0x5f, 0xaf},
{0xaf, 0x5f, 0xd7},
{0xaf, 0x5f, 0xff},
{0xaf, 0x87, 0x00},
{0xaf, 0x87, 0x5f},
{0xaf, 0x87, 0x87},
{0xaf, 0x87, 0xaf},
{0xaf, 0x87, 0xd7},
{0xaf, 0x87, 0xff},
{0xaf, 0xaf, 0x00},
{0xaf, 0xaf, 0x5f},
{0xaf, 0xaf, 0x87},
{0xaf, 0xaf, 0xaf},
{0xaf, 0xaf, 0xd7},
{0xaf, 0xaf, 0xff},
{0xaf, 0xd7, 0x00},
{0xaf, 0xd7, 0x5f},
{0xaf, 0xd7, 0x87},
{0xaf, 0xd7, 0xaf},
{0xaf, 0xd7, 0xd7},
{0xaf, 0xd7, 0xff},
{0xaf, 0xff, 0x00},
{0xaf, 0xff, 0x5f},
{0xaf, 0xff, 0x87},
{0xaf, 0xff, 0xaf},
{0xaf, 0xff, 0xd7},
{0xaf, 0xff, 0xff},
{0xd7, 0x00, 0x00},
{0xd7, 0x00, 0x5f},
{0xd7, 0x00, 0x87},
{0xd7, 0x00, 0xaf},
{0xd7, 0x00, 0xd7},
{0xd7, 0x00, 0xff},
{0xd7, 0x5f, 0x00},
{0xd7, 0x5f, 0x5f},
{0xd7, 0x5f, 0x87},
{0xd7, 0x5f, 0xaf},
{0xd7, 0x5f, 0xd7},
{0xd7, 0x5f, 0xff},
{0xd7, 0x87, 0x00},
{0xd7, 0x87, 0x5f},
{0xd7, 0x87, 0x87},
{0xd7, 0x87, 0xaf},
{0xd7, 0x87, 0xd7},
{0xd7, 0x87, 0xff},
{0xd7, 0xaf, 0x00},
{0xd7, 0xaf, 0x5f},
{0xd7, 0xaf, 0x87},
{0xd7, 0xaf, 0xaf},
{0xd7, 0xaf, 0xd7},
{0xd7, 0xaf, 0xff},
{0xd7, 0xd7, 0x00},
{0xd7, 0xd7, 0x5f},
{0xd7, 0xd7, 0x87},
{0xd7, 0xd7, 0xaf},
{0xd7, 0xd7, 0xd7},
{0xd7, 0xd7, 0xff},
{0xd7, 0xff, 0x00},
{0xd7, 0xff, 0x5f},
{0xd7, 0xff, 0x87},
{0xd7, 0xff, 0xaf},
{0xd7, 0xff, 0xd7},
{0xd7, 0xff, 0xff},
{0xff, 0x00, 0x00},
{0xff, 0x00, 0x5f},
{0xff, 0x00, 0x87},
{0xff, 0x00, 0xaf},
{0xff, 0x00, 0xd7},
{0xff, 0x00, 0xff},
{0xff, 0x5f, 0x00},
{0xff, 0x5f, 0x5f},
{0xff, 0x5f, 0x87},
{0xff, 0x5f, 0xaf},
{0xff, 0x5f, 0xd7},
{0xff, 0x5f, 0xff},
{0xff, 0x87, 0x00},
{0xff, 0x87, 0x5f},
{0xff, 0x87, 0x87},
{0xff, 0x87, 0xaf},
{0xff, 0x87, 0xd7},
{0xff, 0x87, 0xff},
{0xff, 0xaf, 0x00},
{0xff, 0xaf, 0x5f},
{0xff, 0xaf, 0x87},
{0xff, 0xaf, 0xaf},
{0xff, 0xaf, 0xd7},
{0xff, 0xaf, 0xff},
{0xff, 0xd7, 0x00},
{0xff, 0xd7, 0x5f},
{0xff, 0xd7, 0x87},
{0xff, 0xd7, 0xaf},
{0xff, 0xd7, 0xd7},
{0xff, 0xd7, 0xff},
{0xff, 0xff, 0x00},
{0xff, 0xff, 0x5f},
{0xff, 0xff, 0x87},
{0xff, 0xff, 0xaf},
{0xff, 0xff, 0xd7},
{0xff, 0xff, 0xff},
/* 232..255: xterm256 grayscale */
{0x08, 0x08, 0x08}, /* 8 */
{0x12, 0x12, 0x12}, /* 10 */
{0x1c, 0x1c, 0x1c}, /* 10 */
{0x26, 0x26, 0x26}, /* 10 */
{0x30, 0x30, 0x30}, /* .. */
{0x3a, 0x3a, 0x3a},
{0x44, 0x44, 0x44},
{0x4e, 0x4e, 0x4e},
{0x58, 0x58, 0x58},
{0x62, 0x62, 0x62},
{0x6c, 0x6c, 0x6c},
{0x76, 0x76, 0x76},
{0x80, 0x80, 0x80},
{0x8a, 0x8a, 0x8a},
{0x94, 0x94, 0x94},
{0x9e, 0x9e, 0x9e},
{0xa8, 0xa8, 0xa8},
{0xb2, 0xb2, 0xb2},
{0xbc, 0xbc, 0xbc},
{0xc6, 0xc6, 0xc6},
{0xd0, 0xd0, 0xd0},
{0xda, 0xda, 0xda},
{0xe4, 0xe4, 0xe4},
{0xee, 0xee, 0xee},
};
const struct Rgb kXtermRgbAppleFg[] = {
{0, 0, 0}, {192, 55, 41}, {48, 187, 49}, {173, 172, 53},
{73, 76, 224}, {209, 65, 209}, {60, 187, 199}, {203, 204, 205},
{154, 155, 156}, {249, 59, 44}, {62, 229, 55}, {234, 234, 62},
{89, 63, 251}, {247, 67, 245}, {48, 239, 239}, {233, 235, 235},
{47, 49, 49}, {60, 46, 142}, {67, 51, 180}, {74, 56, 218},
{82, 62, 248}, {89, 63, 251}, {46, 127, 43}, {46, 127, 127},
{49, 127, 167}, {60, 127, 207}, {63, 127, 241}, {70, 126, 251},
{57, 161, 50}, {47, 161, 122}, {50, 161, 161}, {60, 161, 200},
{53, 161, 237}, {65, 160, 252}, {45, 194, 51}, {58, 194, 118},
{51, 194, 156}, {59, 194, 194}, {48, 194, 233}, {63, 194, 252},
{62, 227, 55}, {55, 227, 115}, {48, 227, 151}, {63, 227, 189},
{52, 227, 227}, {66, 227, 253}, {51, 252, 57}, {53, 252, 111},
{63, 252, 147}, {58, 252, 184}, {59, 252, 222}, {62, 253, 251},
{138, 49, 43}, {134, 55, 134}, {134, 58, 174}, {133, 61, 213},
{134, 67, 244}, {134, 65, 251}, {125, 124, 46}, {124, 125, 125},
{122, 125, 165}, {123, 126, 205}, {124, 126, 243}, {125, 125, 251},
{120, 159, 47}, {118, 159, 121}, {118, 159, 160}, {117, 160, 199},
{118, 160, 238}, {119, 160, 252}, {115, 193, 53}, {113, 193, 117},
{114, 193, 155}, {111, 193, 193}, {113, 194, 232}, {112, 193, 252},
{110, 226, 53}, {108, 226, 114}, {110, 226, 151}, {106, 226, 189},
{105, 227, 227}, {105, 226, 252}, {99, 251, 59}, {103, 251, 111},
{104, 251, 146}, {97, 252, 184}, {102, 252, 221}, {98, 254, 250},
{175, 54, 40}, {172, 58, 130}, {170, 61, 170}, {170, 66, 210},
{169, 67, 245}, {168, 69, 251}, {164, 123, 47}, {162, 123, 124},
{161, 124, 163}, {161, 124, 203}, {160, 125, 238}, {160, 125, 251},
{158, 157, 47}, {157, 158, 120}, {157, 158, 159}, {155, 158, 198},
{155, 159, 236}, {155, 158, 252}, {153, 192, 55}, {152, 192, 117},
{151, 192, 154}, {151, 192, 193}, {150, 192, 231}, {150, 192, 251},
{148, 225, 53}, {147, 225, 114}, {146, 225, 150}, {147, 226, 188},
{145, 226, 226}, {145, 226, 250}, {142, 251, 61}, {141, 251, 111},
{141, 252, 146}, {142, 253, 183}, {139, 254, 221}, {138, 255, 249},
{211, 59, 40}, {209, 63, 126}, {207, 63, 166}, {206, 64, 206},
{205, 69, 243}, {204, 72, 252}, {202, 121, 45}, {201, 122, 122},
{200, 122, 161}, {199, 123, 200}, {199, 124, 238}, {197, 124, 252},
{197, 156, 51}, {195, 156, 119}, {195, 157, 157}, {194, 157, 196},
{193, 157, 234}, {193, 157, 252}, {191, 190, 54}, {190, 190, 116},
{189, 191, 153}, {190, 191, 191}, {188, 191, 229}, {187, 191, 251},
{186, 224, 55}, {185, 224, 113}, {184, 224, 150}, {184, 224, 187},
{184, 225, 225}, {182, 224, 251}, {180, 253, 62}, {180, 253, 111},
{179, 253, 146}, {179, 253, 183}, {179, 254, 220}, {177, 252, 249},
{244, 59, 43}, {243, 62, 123}, {241, 65, 162}, {241, 69, 202},
{240, 70, 238}, {238, 69, 252}, {239, 119, 50}, {238, 120, 120},
{236, 121, 159}, {235, 121, 198}, {235, 123, 236}, {234, 123, 252},
{234, 154, 53}, {233, 154, 118}, {232, 155, 156}, {231, 155, 194},
{231, 156, 233}, {230, 156, 252}, {229, 188, 53}, {228, 189, 115},
{227, 189, 152}, {227, 189, 190}, {226, 189, 228}, {225, 189, 253},
{223, 222, 60}, {223, 223, 113}, {222, 223, 149}, {222, 223, 186},
{222, 223, 224}, {220, 223, 252}, {218, 251, 61}, {217, 251, 109},
{217, 251, 145}, {217, 251, 182}, {216, 251, 219}, {216, 251, 250},
{252, 63, 43}, {252, 64, 120}, {252, 64, 159}, {252, 65, 198},
{252, 67, 236}, {252, 72, 252}, {253, 117, 47}, {253, 118, 118},
{253, 119, 156}, {253, 120, 194}, {253, 120, 233}, {252, 121, 252},
{253, 152, 49}, {252, 152, 116}, {252, 153, 153}, {253, 153, 192},
{252, 154, 229}, {251, 154, 251}, {253, 186, 56}, {251, 187, 114},
{251, 187, 151}, {252, 187, 188}, {252, 188, 226}, {251, 188, 251},
{251, 221, 61}, {250, 221, 112}, {250, 221, 148}, {250, 221, 185},
{251, 222, 222}, {251, 222, 251}, {251, 250, 58}, {250, 250, 109},
{249, 250, 144}, {247, 251, 181}, {247, 253, 218}, {254, 255, 255},
{52, 53, 53}, {57, 58, 59}, {66, 67, 67}, {75, 76, 76},
{84, 85, 85}, {92, 93, 94}, {101, 102, 102}, {109, 111, 111},
{118, 119, 119}, {126, 127, 128}, {134, 136, 136}, {143, 144, 145},
{151, 152, 153}, {159, 161, 161}, {167, 169, 169}, {176, 177, 177},
{184, 185, 186}, {192, 193, 194}, {200, 201, 202}, {208, 209, 210},
{216, 218, 218}, {224, 226, 226}, {232, 234, 234}, {240, 242, 242},
};
const struct Rgb kXtermRgbAppleBg[] = {
{0, 0, 0}, {151, 4, 12}, {23, 164, 26}, {153, 152, 29},
{8, 43, 181}, {177, 25, 176}, {26, 166, 177}, {191, 191, 191},
{132, 132, 132}, {227, 10, 23}, {33, 215, 38}, {229, 228, 49},
{11, 36, 251}, {227, 35, 227}, {39, 229, 228}, {230, 229, 230},
{0, 0, 0}, {1, 7, 93}, {3, 14, 133}, {5, 21, 172},
{7, 28, 211}, {11, 36, 251}, {8, 94, 11}, {10, 95, 95},
{11, 96, 133}, {13, 97, 173}, {15, 99, 212}, {18, 101, 251},
{17, 134, 20}, {18, 134, 96}, {18, 135, 134}, {20, 136, 173},
{21, 137, 212}, {23, 138, 251}, {25, 173, 29}, {26, 174, 98},
{26, 174, 136}, {27, 175, 174}, {28, 175, 213}, {30, 176, 252},
{33, 213, 38}, {34, 213, 101}, {34, 214, 137}, {35, 214, 175},
{36, 215, 214}, {37, 215, 253}, {41, 253, 47}, {42, 253, 104},
{42, 253, 140}, {43, 253, 177}, {44, 254, 215}, {45, 255, 254},
{94, 2, 4}, {94, 8, 94}, {94, 15, 133}, {94, 22, 172},
{95, 29, 211}, {95, 36, 251}, {95, 94, 14}, {95, 95, 95},
{95, 96, 134}, {95, 97, 173}, {96, 99, 212}, {96, 101, 251},
{96, 134, 22}, {96, 134, 96}, {96, 135, 135}, {97, 136, 173},
{97, 137, 212}, {97, 138, 252}, {98, 173, 30}, {98, 174, 98},
{98, 174, 136}, {98, 175, 174}, {98, 176, 213}, {99, 177, 252},
{100, 213, 39}, {100, 213, 101}, {100, 214, 138}, {100, 214, 176},
{101, 215, 214}, {101, 215, 253}, {102, 253, 48}, {103, 253, 104},
{103, 253, 140}, {103, 253, 177}, {103, 254, 215}, {104, 255, 254},
{133, 3, 9}, {133, 10, 94}, {134, 16, 133}, {134, 23, 172},
{134, 30, 212}, {134, 37, 251}, {134, 94, 18}, {134, 95, 96},
{134, 96, 134}, {134, 97, 173}, {135, 99, 212}, {135, 101, 251},
{135, 134, 25}, {135, 134, 97}, {135, 135, 135}, {135, 136, 174},
{135, 137, 213}, {136, 138, 252}, {136, 173, 32}, {136, 174, 99},
{136, 174, 136}, {136, 175, 175}, {136, 176, 213}, {137, 177, 252},
{137, 213, 40}, {137, 213, 102}, {138, 214, 138}, {138, 214, 176},
{138, 215, 214}, {138, 216, 253}, {139, 253, 49}, {139, 253, 105},
{139, 253, 140}, {139, 254, 178}, {140, 254, 216}, {140, 255, 254},
{173, 6, 15}, {173, 12, 95}, {173, 18, 134}, {173, 24, 173},
{173, 31, 212}, {174, 38, 251}, {173, 95, 22}, {174, 95, 96},
{174, 96, 135}, {174, 98, 173}, {174, 99, 212}, {174, 101, 252},
{174, 134, 28}, {174, 135, 98}, {174, 135, 136}, {174, 136, 174},
{174, 137, 213}, {175, 139, 252}, {175, 174, 35}, {175, 174, 100},
{175, 174, 137}, {175, 175, 175}, {175, 176, 214}, {175, 177, 253},
{176, 213, 43}, {176, 213, 102}, {176, 214, 139}, {176, 214, 176},
{176, 215, 215}, {176, 216, 253}, {177, 253, 51}, {177, 253, 105},
{177, 253, 141}, {177, 254, 178}, {178, 254, 216}, {178, 255, 254},
{213, 9, 21}, {213, 15, 96}, {213, 20, 135}, {241, 69, 202},
{213, 32, 212}, {213, 39, 251}, {213, 95, 27}, {213, 96, 97},
{213, 97, 135}, {213, 98, 174}, {213, 100, 213}, {213, 102, 252},
{213, 134, 32}, {213, 135, 99}, {213, 135, 136}, {214, 136, 175},
{214, 137, 213}, {214, 139, 252}, {214, 174, 38}, {214, 174, 101},
{214, 175, 138}, {214, 175, 176}, {214, 176, 214}, {214, 177, 253},
{215, 213, 45}, {215, 214, 103}, {215, 214, 139}, {215, 214, 177},
{215, 215, 215}, {215, 216, 254}, {216, 253, 53}, {216, 253, 106},
{216, 253, 141}, {216, 254, 178}, {216, 254, 216}, {216, 255, 255},
{252, 13, 27}, {252, 18, 98}, {252, 22, 135}, {252, 28, 174},
{252, 34, 213}, {252, 40, 252}, {252, 96, 32}, {252, 96, 99},
{252, 97, 136}, {253, 99, 175}, {253, 100, 213}, {253, 102, 252},
{253, 135, 36}, {253, 135, 100}, {253, 136, 137}, {253, 137, 175},
{253, 138, 214}, {253, 139, 253}, {253, 174, 42}, {253, 174, 102},
{253, 175, 138}, {253, 175, 176}, {253, 176, 215}, {254, 177, 253},
{254, 213, 48}, {254, 214, 105}, {254, 214, 140}, {254, 215, 177},
{254, 215, 216}, {254, 216, 254}, {255, 253, 56}, {255, 253, 108},
{255, 253, 142}, {255, 254, 179}, {255, 254, 217}, {255, 255, 255},
{8, 8, 8}, {18, 18, 18}, {28, 28, 28}, {38, 38, 38},
{48, 48, 48}, {58, 58, 58}, {68, 68, 68}, {78, 78, 78},
{88, 88, 88}, {98, 98, 98}, {108, 108, 108}, {118, 118, 118},
{128, 128, 128}, {138, 138, 138}, {148, 148, 148}, {158, 158, 158},
{168, 168, 168}, {178, 178, 178}, {188, 188, 188}, {198, 198, 198},
{208, 208, 208}, {218, 218, 218}, {228, 228, 228}, {238, 238, 238},
};
const struct XtermDb {
struct Rgb rgb;
const char *text;
} kXtermDb[] = {
{{0x00, 0x00, 0x00}, "0 Black #000000"},
{{0x80, 0x00, 0x00}, "1 Maroon #800000"},
{{0x00, 0x80, 0x00}, "2 Green #008000"},
{{0x80, 0x80, 0x00}, "3 Olive #808000"},
{{0x00, 0x00, 0x80}, "4 Navy #000080"},
{{0x80, 0x00, 0x80}, "5 Purple #800080"},
{{0x00, 0x80, 0x80}, "6 Teal #008080"},
{{0xc0, 0xc0, 0xc0}, "7 Silver #c0c0c0"},
{{0x80, 0x80, 0x80}, "8 Grey #808080"},
{{0xff, 0x00, 0x00}, "9 Red #ff0000"},
{{0x00, 0xff, 0x00}, "10 Lime #00ff00"},
{{0xff, 0xff, 0x00}, "11 Yellow #ffff00"},
{{0x00, 0x00, 0xff}, "12 Blue #0000ff"},
{{0xff, 0x00, 0xff}, "13 Fuchsia #ff00ff"},
{{0x00, 0xff, 0xff}, "14 Aqua #00ffff"},
{{0xff, 0xff, 0xff}, "15 White #ffffff"},
{{0x00, 0x00, 0x00}, "16 Grey0 #000000"},
{{0x00, 0x00, 0x5f}, "17 NavyBlue #00005f"},
{{0x00, 0x00, 0x87}, "18 DarkBlue #000087"},
{{0x00, 0x00, 0xaf}, "19 Blue3 #0000af"},
{{0x00, 0x00, 0xd7}, "20 Blue3 #0000d7"},
{{0x00, 0x00, 0xff}, "21 Blue1 #0000ff"},
{{0x00, 0x5f, 0x00}, "22 DarkGreen #005f00"},
{{0x00, 0x5f, 0x5f}, "23 DeepSkyBlue4 #005f5f"},
{{0x00, 0x5f, 0x87}, "24 DeepSkyBlue4 #005f87"},
{{0x00, 0x5f, 0xaf}, "25 DeepSkyBlue4 #005faf"},
{{0x00, 0x5f, 0xd7}, "26 DodgerBlue3 #005fd7"},
{{0x00, 0x5f, 0xff}, "27 DodgerBlue2 #005fff"},
{{0x00, 0x87, 0x00}, "28 Green4 #008700"},
{{0x00, 0x87, 0x5f}, "29 SpringGreen4 #00875f"},
{{0x00, 0x87, 0x87}, "30 Turquoise4 #008787"},
{{0x00, 0x87, 0xaf}, "31 DeepSkyBlue3 #0087af"},
{{0x00, 0x87, 0xd7}, "32 DeepSkyBlue3 #0087d7"},
{{0x00, 0x87, 0xff}, "33 DodgerBlue1 #0087ff"},
{{0x00, 0xaf, 0x00}, "34 Green3 #00af00"},
{{0x00, 0xaf, 0x5f}, "35 SpringGreen3 #00af5f"},
{{0x00, 0xaf, 0x87}, "36 DarkCyan #00af87"},
{{0x00, 0xaf, 0xaf}, "37 LightSeaGreen #00afaf"},
{{0x00, 0xaf, 0xd7}, "38 DeepSkyBlue2 #00afd7"},
{{0x00, 0xaf, 0xff}, "39 DeepSkyBlue1 #00afff"},
{{0x00, 0xd7, 0x00}, "40 Green3 #00d700"},
{{0x00, 0xd7, 0x5f}, "41 SpringGreen3 #00d75f"},
{{0x00, 0xd7, 0x87}, "42 SpringGreen2 #00d787"},
{{0x00, 0xd7, 0xaf}, "43 Cyan3 #00d7af"},
{{0x00, 0xd7, 0xd7}, "44 DarkTurquoise #00d7d7"},
{{0x00, 0xd7, 0xff}, "45 Turquoise2 #00d7ff"},
{{0x00, 0xff, 0x00}, "46 Green1 #00ff00"},
{{0x00, 0xff, 0x5f}, "47 SpringGreen2 #00ff5f"},
{{0x00, 0xff, 0x87}, "48 SpringGreen1 #00ff87"},
{{0x00, 0xff, 0xaf}, "49 MediumSpringGreen #00ffaf"},
{{0x00, 0xff, 0xd7}, "50 Cyan2 #00ffd7"},
{{0x00, 0xff, 0xff}, "51 Cyan1 #00ffff"},
{{0x5f, 0x00, 0x00}, "52 DarkRed #5f0000"},
{{0x5f, 0x00, 0x5f}, "53 DeepPink4 #5f005f"},
{{0x5f, 0x00, 0x87}, "54 Purple4 #5f0087"},
{{0x5f, 0x00, 0xaf}, "55 Purple4 #5f00af"},
{{0x5f, 0x00, 0xd7}, "56 Purple3 #5f00d7"},
{{0x5f, 0x00, 0xff}, "57 BlueViolet #5f00ff"},
{{0x5f, 0x5f, 0x00}, "58 Orange4 #5f5f00"},
{{0x5f, 0x5f, 0x5f}, "59 Grey37 #5f5f5f"},
{{0x5f, 0x5f, 0x87}, "60 MediumPurple4 #5f5f87"},
{{0x5f, 0x5f, 0xaf}, "61 SlateBlue3 #5f5faf"},
{{0x5f, 0x5f, 0xd7}, "62 SlateBlue3 #5f5fd7"},
{{0x5f, 0x5f, 0xff}, "63 RoyalBlue1 #5f5fff"},
{{0x5f, 0x87, 0x00}, "64 Chartreuse4 #5f8700"},
{{0x5f, 0x87, 0x5f}, "65 DarkSeaGreen4 #5f875f"},
{{0x5f, 0x87, 0x87}, "66 PaleTurquoise4 #5f8787"},
{{0x5f, 0x87, 0xaf}, "67 SteelBlue #5f87af"},
{{0x5f, 0x87, 0xd7}, "68 SteelBlue3 #5f87d7"},
{{0x5f, 0x87, 0xff}, "69 CornflowerBlue #5f87ff"},
{{0x5f, 0xaf, 0x00}, "70 Chartreuse3 #5faf00"},
{{0x5f, 0xaf, 0x5f}, "71 DarkSeaGreen4 #5faf5f"},
{{0x5f, 0xaf, 0x87}, "72 CadetBlue #5faf87"},
{{0x5f, 0xaf, 0xaf}, "73 CadetBlue #5fafaf"},
{{0x5f, 0xaf, 0xd7}, "74 SkyBlue3 #5fafd7"},
{{0x5f, 0xaf, 0xff}, "75 SteelBlue1 #5fafff"},
{{0x5f, 0xd7, 0x00}, "76 Chartreuse3 #5fd700"},
{{0x5f, 0xd7, 0x5f}, "77 PaleGreen3 #5fd75f"},
{{0x5f, 0xd7, 0x87}, "78 SeaGreen3 #5fd787"},
{{0x5f, 0xd7, 0xaf}, "79 Aquamarine3 #5fd7af"},
{{0x5f, 0xd7, 0xd7}, "80 MediumTurquoise #5fd7d7"},
{{0x5f, 0xd7, 0xff}, "81 SteelBlue1 #5fd7ff"},
{{0x5f, 0xff, 0x00}, "82 Chartreuse2 #5fff00"},
{{0x5f, 0xff, 0x5f}, "83 SeaGreen2 #5fff5f"},
{{0x5f, 0xff, 0x87}, "84 SeaGreen1 #5fff87"},
{{0x5f, 0xff, 0xaf}, "85 SeaGreen1 #5fffaf"},
{{0x5f, 0xff, 0xd7}, "86 Aquamarine1 #5fffd7"},
{{0x5f, 0xff, 0xff}, "87 DarkSlateGray2 #5fffff"},
{{0x87, 0x00, 0x00}, "88 DarkRed #870000"},
{{0x87, 0x00, 0x5f}, "89 DeepPink4 #87005f"},
{{0x87, 0x00, 0x87}, "90 DarkMagenta #870087"},
{{0x87, 0x00, 0xaf}, "91 DarkMagenta #8700af"},
{{0x87, 0x00, 0xd7}, "92 DarkViolet #8700d7"},
{{0x87, 0x00, 0xff}, "93 Purple #8700ff"},
{{0x87, 0x5f, 0x00}, "94 Orange4 #875f00"},
{{0x87, 0x5f, 0x5f}, "95 LightPink4 #875f5f"},
{{0x87, 0x5f, 0x87}, "96 Plum4 #875f87"},
{{0x87, 0x5f, 0xaf}, "97 MediumPurple3 #875faf"},
{{0x87, 0x5f, 0xd7}, "98 MediumPurple3 #875fd7"},
{{0x87, 0x5f, 0xff}, "99 SlateBlue1 #875fff"},
{{0x87, 0x87, 0x00}, "100 Yellow4 #878700"},
{{0x87, 0x87, 0x5f}, "101 Wheat4 #87875f"},
{{0x87, 0x87, 0x87}, "102 Grey53 #878787"},
{{0x87, 0x87, 0xaf}, "103 LightSlateGrey #8787af"},
{{0x87, 0x87, 0xd7}, "104 MediumPurple #8787d7"},
{{0x87, 0x87, 0xff}, "105 LightSlateBlue #8787ff"},
{{0x87, 0xaf, 0x00}, "106 Yellow4 #87af00"},
{{0x87, 0xaf, 0x5f}, "107 DarkOliveGreen3 #87af5f"},
{{0x87, 0xaf, 0x87}, "108 DarkSeaGreen #87af87"},
{{0x87, 0xaf, 0xaf}, "109 LightSkyBlue3 #87afaf"},
{{0x87, 0xaf, 0xd7}, "110 LightSkyBlue3 #87afd7"},
{{0x87, 0xaf, 0xff}, "111 SkyBlue2 #87afff"},
{{0x87, 0xd7, 0x00}, "112 Chartreuse2 #87d700"},
{{0x87, 0xd7, 0x5f}, "113 DarkOliveGreen3 #87d75f"},
{{0x87, 0xd7, 0x87}, "114 PaleGreen3 #87d787"},
{{0x87, 0xd7, 0xaf}, "115 DarkSeaGreen3 #87d7af"},
{{0x87, 0xd7, 0xd7}, "116 DarkSlateGray3 #87d7d7"},
{{0x87, 0xd7, 0xff}, "117 SkyBlue1 #87d7ff"},
{{0x87, 0xff, 0x00}, "118 Chartreuse1 #87ff00"},
{{0x87, 0xff, 0x5f}, "119 LightGreen #87ff5f"},
{{0x87, 0xff, 0x87}, "120 LightGreen #87ff87"},
{{0x87, 0xff, 0xaf}, "121 PaleGreen1 #87ffaf"},
{{0x87, 0xff, 0xd7}, "122 Aquamarine1 #87ffd7"},
{{0x87, 0xff, 0xff}, "123 DarkSlateGray1 #87ffff"},
{{0xaf, 0x00, 0x00}, "124 Red3 #af0000"},
{{0xaf, 0x00, 0x5f}, "125 DeepPink4 #af005f"},
{{0xaf, 0x00, 0x87}, "126 MediumVioletRed #af0087"},
{{0xaf, 0x00, 0xaf}, "127 Magenta3 #af00af"},
{{0xaf, 0x00, 0xd7}, "128 DarkViolet #af00d7"},
{{0xaf, 0x00, 0xff}, "129 Purple #af00ff"},
{{0xaf, 0x5f, 0x00}, "130 DarkOrange3 #af5f00"},
{{0xaf, 0x5f, 0x5f}, "131 IndianRed #af5f5f"},
{{0xaf, 0x5f, 0x87}, "132 HotPink3 #af5f87"},
{{0xaf, 0x5f, 0xaf}, "133 MediumOrchid3 #af5faf"},
{{0xaf, 0x5f, 0xd7}, "134 MediumOrchid #af5fd7"},
{{0xaf, 0x5f, 0xff}, "135 MediumPurple2 #af5fff"},
{{0xaf, 0x87, 0x00}, "136 DarkGoldenrod #af8700"},
{{0xaf, 0x87, 0x5f}, "137 LightSalmon3 #af875f"},
{{0xaf, 0x87, 0x87}, "138 RosyBrown #af8787"},
{{0xaf, 0x87, 0xaf}, "139 Grey63 #af87af"},
{{0xaf, 0x87, 0xd7}, "140 MediumPurple2 #af87d7"},
{{0xaf, 0x87, 0xff}, "141 MediumPurple1 #af87ff"},
{{0xaf, 0xaf, 0x00}, "142 Gold3 #afaf00"},
{{0xaf, 0xaf, 0x5f}, "143 DarkKhaki #afaf5f"},
{{0xaf, 0xaf, 0x87}, "144 NavajoWhite3 #afaf87"},
{{0xaf, 0xaf, 0xaf}, "145 Grey69 #afafaf"},
{{0xaf, 0xaf, 0xd7}, "146 LightSteelBlue3 #afafd7"},
{{0xaf, 0xaf, 0xff}, "147 LightSteelBlue #afafff"},
{{0xaf, 0xd7, 0x00}, "148 Yellow3 #afd700"},
{{0xaf, 0xd7, 0x5f}, "149 DarkOliveGreen3 #afd75f"},
{{0xaf, 0xd7, 0x87}, "150 DarkSeaGreen3 #afd787"},
{{0xaf, 0xd7, 0xaf}, "151 DarkSeaGreen2 #afd7af"},
{{0xaf, 0xd7, 0xd7}, "152 LightCyan3 #afd7d7"},
{{0xaf, 0xd7, 0xff}, "153 LightSkyBlue1 #afd7ff"},
{{0xaf, 0xff, 0x00}, "154 GreenYellow #afff00"},
{{0xaf, 0xff, 0x5f}, "155 DarkOliveGreen2 #afff5f"},
{{0xaf, 0xff, 0x87}, "156 PaleGreen1 #afff87"},
{{0xaf, 0xff, 0xaf}, "157 DarkSeaGreen2 #afffaf"},
{{0xaf, 0xff, 0xd7}, "158 DarkSeaGreen1 #afffd7"},
{{0xaf, 0xff, 0xff}, "159 PaleTurquoise1 #afffff"},
{{0xd7, 0x00, 0x00}, "160 Red3 #d70000"},
{{0xd7, 0x00, 0x5f}, "161 DeepPink3 #d7005f"},
{{0xd7, 0x00, 0x87}, "162 DeepPink3 #d70087"},
{{0xd7, 0x00, 0xaf}, "163 Magenta3 #d700af"},
{{0xd7, 0x00, 0xd7}, "164 Magenta3 #d700d7"},
{{0xd7, 0x00, 0xff}, "165 Magenta2 #d700ff"},
{{0xd7, 0x5f, 0x00}, "166 DarkOrange3 #d75f00"},
{{0xd7, 0x5f, 0x5f}, "167 IndianRed #d75f5f"},
{{0xd7, 0x5f, 0x87}, "168 HotPink3 #d75f87"},
{{0xd7, 0x5f, 0xaf}, "169 HotPink2 #d75faf"},
{{0xd7, 0x5f, 0xd7}, "170 Orchid #d75fd7"},
{{0xd7, 0x5f, 0xff}, "171 MediumOrchid1 #d75fff"},
{{0xd7, 0x87, 0x00}, "172 Orange3 #d78700"},
{{0xd7, 0x87, 0x5f}, "173 LightSalmon3 #d7875f"},
{{0xd7, 0x87, 0x87}, "174 LightPink3 #d78787"},
{{0xd7, 0x87, 0xaf}, "175 Pink3 #d787af"},
{{0xd7, 0x87, 0xd7}, "176 Plum3 #d787d7"},
{{0xd7, 0x87, 0xff}, "177 Violet #d787ff"},
{{0xd7, 0xaf, 0x00}, "178 Gold3 #d7af00"},
{{0xd7, 0xaf, 0x5f}, "179 LightGoldenrod3 #d7af5f"},
{{0xd7, 0xaf, 0x87}, "180 Tan #d7af87"},
{{0xd7, 0xaf, 0xaf}, "181 MistyRose3 #d7afaf"},
{{0xd7, 0xaf, 0xd7}, "182 Thistle3 #d7afd7"},
{{0xd7, 0xaf, 0xff}, "183 Plum2 #d7afff"},
{{0xd7, 0xd7, 0x00}, "184 Yellow3 #d7d700"},
{{0xd7, 0xd7, 0x5f}, "185 Khaki3 #d7d75f"},
{{0xd7, 0xd7, 0x87}, "186 LightGoldenrod2 #d7d787"},
{{0xd7, 0xd7, 0xaf}, "187 LightYellow3 #d7d7af"},
{{0xd7, 0xd7, 0xd7}, "188 Grey84 #d7d7d7"},
{{0xd7, 0xd7, 0xff}, "189 LightSteelBlue1 #d7d7ff"},
{{0xd7, 0xff, 0x00}, "190 Yellow2 #d7ff00"},
{{0xd7, 0xff, 0x5f}, "191 DarkOliveGreen1 #d7ff5f"},
{{0xd7, 0xff, 0x87}, "192 DarkOliveGreen1 #d7ff87"},
{{0xd7, 0xff, 0xaf}, "193 DarkSeaGreen1 #d7ffaf"},
{{0xd7, 0xff, 0xd7}, "194 Honeydew2 #d7ffd7"},
{{0xd7, 0xff, 0xff}, "195 LightCyan1 #d7ffff"},
{{0xff, 0x00, 0x00}, "196 Red1 #ff0000"},
{{0xff, 0x00, 0x5f}, "197 DeepPink2 #ff005f"},
{{0xff, 0x00, 0x87}, "198 DeepPink1 #ff0087"},
{{0xff, 0x00, 0xaf}, "199 DeepPink1 #ff00af"},
{{0xff, 0x00, 0xd7}, "200 Magenta2 #ff00d7"},
{{0xff, 0x00, 0xff}, "201 Magenta1 #ff00ff"},
{{0xff, 0x5f, 0x00}, "202 OrangeRed1 #ff5f00"},
{{0xff, 0x5f, 0x5f}, "203 IndianRed1 #ff5f5f"},
{{0xff, 0x5f, 0x87}, "204 IndianRed1 #ff5f87"},
{{0xff, 0x5f, 0xaf}, "205 HotPink #ff5faf"},
{{0xff, 0x5f, 0xd7}, "206 HotPink #ff5fd7"},
{{0xff, 0x5f, 0xff}, "207 MediumOrchid1 #ff5fff"},
{{0xff, 0x87, 0x00}, "208 DarkOrange #ff8700"},
{{0xff, 0x87, 0x5f}, "209 Salmon1 #ff875f"},
{{0xff, 0x87, 0x87}, "210 LightCoral #ff8787"},
{{0xff, 0x87, 0xaf}, "211 PaleVioletRed1 #ff87af"},
{{0xff, 0x87, 0xd7}, "212 Orchid2 #ff87d7"},
{{0xff, 0x87, 0xff}, "213 Orchid1 #ff87ff"},
{{0xff, 0xaf, 0x00}, "214 Orange1 #ffaf00"},
{{0xff, 0xaf, 0x5f}, "215 SandyBrown #ffaf5f"},
{{0xff, 0xaf, 0x87}, "216 LightSalmon1 #ffaf87"},
{{0xff, 0xaf, 0xaf}, "217 LightPink1 #ffafaf"},
{{0xff, 0xaf, 0xd7}, "218 Pink1 #ffafd7"},
{{0xff, 0xaf, 0xff}, "219 Plum1 #ffafff"},
{{0xff, 0xd7, 0x00}, "220 Gold1 #ffd700"},
{{0xff, 0xd7, 0x5f}, "221 LightGoldenrod2 #ffd75f"},
{{0xff, 0xd7, 0x87}, "222 LightGoldenrod2 #ffd787"},
{{0xff, 0xd7, 0xaf}, "223 NavajoWhite1 #ffd7af"},
{{0xff, 0xd7, 0xd7}, "224 MistyRose1 #ffd7d7"},
{{0xff, 0xd7, 0xff}, "225 Thistle1 #ffd7ff"},
{{0xff, 0xff, 0x00}, "226 Yellow1 #ffff00"},
{{0xff, 0xff, 0x5f}, "227 LightGoldenrod1 #ffff5f"},
{{0xff, 0xff, 0x87}, "228 Khaki1 #ffff87"},
{{0xff, 0xff, 0xaf}, "229 Wheat1 #ffffaf"},
{{0xff, 0xff, 0xd7}, "230 Cornsilk1 #ffffd7"},
{{0xff, 0xff, 0xff}, "231 Grey100 #ffffff"},
{{0x08, 0x08, 0x08}, "232 Grey3 #080808"},
{{0x12, 0x12, 0x12}, "233 Grey7 #121212"},
{{0x1c, 0x1c, 0x1c}, "234 Grey11 #1c1c1c"},
{{0x26, 0x26, 0x26}, "235 Grey15 #262626"},
{{0x30, 0x30, 0x30}, "236 Grey19 #303030"},
{{0x3a, 0x3a, 0x3a}, "237 Grey23 #3a3a3a"},
{{0x44, 0x44, 0x44}, "238 Grey27 #444444"},
{{0x4e, 0x4e, 0x4e}, "239 Grey30 #4e4e4e"},
{{0x58, 0x58, 0x58}, "240 Grey35 #585858"},
{{0x62, 0x62, 0x62}, "241 Grey39 #626262"},
{{0x6c, 0x6c, 0x6c}, "242 Grey42 #6c6c6c"},
{{0x76, 0x76, 0x76}, "243 Grey46 #767676"},
{{0x80, 0x80, 0x80}, "244 Grey50 #808080"},
{{0x8a, 0x8a, 0x8a}, "245 Grey54 #8a8a8a"},
{{0x94, 0x94, 0x94}, "246 Grey58 #949494"},
{{0x9e, 0x9e, 0x9e}, "247 Grey62 #9e9e9e"},
{{0xa8, 0xa8, 0xa8}, "248 Grey66 #a8a8a8"},
{{0xb2, 0xb2, 0xb2}, "249 Grey70 #b2b2b2"},
{{0xbc, 0xbc, 0xbc}, "250 Grey74 #bcbcbc"},
{{0xc6, 0xc6, 0xc6}, "251 Grey78 #c6c6c6"},
{{0xd0, 0xd0, 0xd0}, "252 Grey82 #d0d0d0"},
{{0xda, 0xda, 0xda}, "253 Grey85 #dadada"},
{{0xe4, 0xe4, 0xe4}, "254 Grey89 #e4e4e4"},
{{0xee, 0xee, 0xee}, "255 Grey93 #eeeeee"},
};
int main(int argc, char *argv[]) {
size_t i;
printf("BG FG BB BF XTERM NAME HEX\n");
for (i = 0; i < 256; ++i) {
printf("\e[48;5;%dm \e[0m \e[38;5;%dm██\e[0m \e[1;48;5;%dm "
"\e[0m \e[1;38;5;%dm██\e[0m %-6hhu%-18s#%02hhx%02hhx%02hhx\n",
i, i, i, i, i, IndexDoubleNulString(kXtermName, i), kXtermRgb[i].r,
kXtermRgb[i].g, kXtermRgb[i].b);
}
return 0;
}