mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Remove some dead code
This commit is contained in:
parent
168d1c157e
commit
73c0faa1b5
66 changed files with 324 additions and 7705 deletions
|
@ -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) */
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
124
third_party/getopt/getopt.c
vendored
124
third_party/getopt/getopt.c
vendored
|
@ -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 */
|
||||
|
|
10
third_party/musl/crypt.internal.h
vendored
10
third_party/musl/crypt.internal.h
vendored
|
@ -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) */
|
||||
|
|
5
third_party/nsync/panic.c
vendored
5
third_party/nsync/panic.c
vendored
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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), "2ˣ")
|
||||
M(1, g, "exp10", Exp10, exp10l(x), "10ˣ")
|
||||
M(2, g, "ldexp", Ldexp, ldexpl(x, y), "𝑥×2ʸ")
|
||||
|
||||
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")
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
251
tool/build/rle.c
251
tool/build/rle.c
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 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 │ │
|
||||
└────────────┴─────────────┴────────────────────────────────┴────────────┘ */
|
||||
#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;
|
||||
}
|
|
@ -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\
|
||||
/ rrrr│uuuu││r│├┐│");
|
||||
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;
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
(require 'ctest-mode)
|
||||
(require 'ld-script)
|
||||
(require 'optinfo-mode)
|
||||
(require 'protobuf-mode)
|
||||
|
|
|
@ -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)
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
156
tool/viz/tcp.c
156
tool/viz/tcp.c
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue