Apply some touchups

This commit is contained in:
Justine Tunney
2021-02-07 06:11:44 -08:00
parent 9f149e1de3
commit 2f3bd90216
139 changed files with 1188 additions and 1154 deletions

View File

@ -18,6 +18,7 @@
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/alg/arraylist2.internal.h"
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/stat.h"
@ -53,6 +54,11 @@
* directory be a .a prerequisite so archives rebuild on file deletion.
*/
struct Args {
size_t n;
char **p;
};
struct String {
size_t i, n;
char *p;
@ -95,14 +101,18 @@ static void MakeHeader(struct Header *h, const char *name, int ref, int mode,
}
int main(int argc, char *argv[]) {
FILE *f;
void *elf;
char *line;
char *strs;
ssize_t rc;
size_t wrote;
size_t remain;
struct stat *st;
uint32_t outpos;
Elf64_Sym *syms;
struct Args args;
uint64_t outsize;
char **objectargs;
uint8_t *tablebuf;
struct iovec iov[7];
const char *symname;
@ -112,7 +122,6 @@ int main(int argc, char *argv[]) {
struct String symbols;
struct String filenames;
struct Header *header1, *header2;
size_t wrote, remain, objectargcount;
int *offsets, *modes, *sizes, *names;
int i, j, fd, err, name, outfd, tablebufsize;
@ -121,6 +130,25 @@ int main(int argc, char *argv[]) {
return 1;
}
memset(&args, 0, sizeof(args));
for (i = 3; i < argc; ++i) {
if (argv[i][0] != '@') {
args.p = realloc(args.p, ++args.n * sizeof(*args.p));
args.p[args.n - 1] = strdup(argv[i]);
} else {
CHECK_NOTNULL((f = fopen(argv[i] + 1, "r")));
while ((line = chomp(xgetline(f)))) {
if (!isempty(line)) {
args.p = realloc(args.p, ++args.n * sizeof(*args.p));
args.p[args.n - 1] = line;
} else {
free(line);
}
}
CHECK_NE(-1, fclose(f));
}
}
st = xmalloc(sizeof(struct stat));
symbols.i = 0;
symbols.n = 4096;
@ -133,32 +161,29 @@ int main(int argc, char *argv[]) {
symnames.p = xmalloc(symnames.n * sizeof(int));
outpath = argv[2];
objectargs = argv + 3;
objectargcount = argc - 3;
modes = xmalloc(sizeof(int) * objectargcount);
names = xmalloc(sizeof(int) * objectargcount);
sizes = xmalloc(sizeof(int) * objectargcount);
modes = xmalloc(sizeof(int) * args.n);
names = xmalloc(sizeof(int) * args.n);
sizes = xmalloc(sizeof(int) * args.n);
// load global symbols and populate page cache
for (i = 0; i < objectargcount; ++i) {
for (i = 0; i < args.n; ++i) {
TryAgain:
CHECK_NE(-1, (fd = open(objectargs[i], O_RDONLY)));
CHECK_NE(-1, (fd = open(args.p[i], O_RDONLY)), "%s", args.p[i]);
CHECK_NE(-1, fstat(fd, st));
CHECK_LT(st->st_size, 0x7ffff000);
if (!st->st_size || S_ISDIR(st->st_mode) ||
endswith(objectargs[i], ".pkg")) {
if (!st->st_size || S_ISDIR(st->st_mode) || endswith(args.p[i], ".pkg")) {
close(fd);
for (j = i; j + 1 < objectargcount; ++j) {
objectargs[j] = objectargs[j + 1];
for (j = i; j + 1 < args.n; ++j) {
args.p[j] = args.p[j + 1];
}
--objectargcount;
--args.n;
goto TryAgain;
}
names[i] = filenames.i;
sizes[i] = st->st_size;
modes[i] = st->st_mode;
CONCAT(&filenames.p, &filenames.i, &filenames.n, basename(objectargs[i]),
strlen(basename(objectargs[i])));
CONCAT(&filenames.p, &filenames.i, &filenames.n, basename(args.p[i]),
strlen(basename(args.p[i])));
CONCAT(&filenames.p, &filenames.i, &filenames.n, "/\n", 2);
CHECK_NE(MAP_FAILED,
(elf = mmap(NULL, st->st_size, PROT_READ, MAP_PRIVATE, fd, 0)));
@ -182,7 +207,7 @@ int main(int argc, char *argv[]) {
outsize = 0;
tablebufsize = 4 + symnames.i * 4;
tablebuf = xmalloc(tablebufsize);
offsets = xmalloc(objectargcount * 4);
offsets = xmalloc(args.n * 4);
header1 = xmalloc(sizeof(struct Header));
header2 = xmalloc(sizeof(struct Header));
iov[0].iov_base = "!<arch>\n";
@ -199,7 +224,7 @@ int main(int argc, char *argv[]) {
outsize += (iov[5].iov_len = 60);
iov[6].iov_base = filenames.p;
outsize += (iov[6].iov_len = filenames.i);
for (i = 0; i < objectargcount; ++i) {
for (i = 0; i < args.n; ++i) {
outsize += outsize & 1;
offsets[i] = outsize;
outsize += 60;
@ -219,8 +244,8 @@ int main(int argc, char *argv[]) {
CHECK_NE(-1, (outfd = open(outpath, O_WRONLY | O_TRUNC | O_CREAT, 0644)));
ftruncate(outfd, outsize);
if ((outsize = writev(outfd, iov, ARRAYLEN(iov))) == -1) goto fail;
for (i = 0; i < objectargcount; ++i) {
if ((fd = open(objectargs[i], O_RDONLY)) == -1) goto fail;
for (i = 0; i < args.n; ++i) {
if ((fd = open(args.p[i], O_RDONLY)) == -1) goto fail;
iov[0].iov_base = "\n";
outsize += (iov[0].iov_len = outsize & 1);
iov[1].iov_base = header1;
@ -233,6 +258,8 @@ int main(int argc, char *argv[]) {
}
close(outfd);
for (i = 0; i < args.n; ++i) free(args.p[i]);
free(args.p);
free(header2);
free(header1);
free(offsets);

337
tool/build/compile.c Normal file
View File

@ -0,0 +1,337 @@
/*-*- 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/bits/safemacros.h"
#include "libc/calls/calls.h"
#include "libc/calls/sigbits.h"
#include "libc/calls/struct/sigset.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/sig.h"
#include "libc/x/x.h"
#define MANUAL \
"\
OVERVIEW\n\
\n\
GNU/LLVM Compiler Collection Frontend Frontend\n\
\n\
DESCRIPTION\n\
\n\
This launches gcc or clang while filtering out\n\
flags they whine about.\n\
\n\
EXAMPLE\n\
\n\
compile.com gcc -o program program.c\n\
\n"
struct Flags {
size_t n;
char **p;
};
struct Command {
size_t n;
char *p;
};
bool iscc;
bool isclang;
bool isgcc;
bool wantasan;
bool wantfentry;
bool wantframe;
bool wantnop;
bool wantnopg;
bool wantpg;
bool wantrecord;
bool wantubsan;
char *cc;
char *colorflag;
char *outdir;
char *outpath;
char ccpath[PATH_MAX];
int ccversion;
struct Flags flags;
struct Command command;
void AddFlag(char *s) {
size_t n;
flags.p = realloc(flags.p, ++flags.n * sizeof(*flags.p));
flags.p[flags.n - 1] = s;
if (s) {
n = strlen(s);
if (command.n) {
command.p = realloc(command.p, command.n + 1 + n);
command.p[command.n] = ' ';
memcpy(command.p + command.n + 1, s, n);
command.n += 1 + n;
} else {
command.p = realloc(command.p, command.n + n);
memcpy(command.p + command.n, s, n);
command.n += n;
}
} else {
command.p = realloc(command.p, command.n + 1);
command.p[command.n] = '\n';
command.n += 1;
}
}
int main(int argc, char *argv[]) {
int i, ws, pid;
sigset_t mask, savemask;
if (argc == 1) {
write(2, MANUAL, sizeof(MANUAL) - 1);
exit(1);
}
if (argc == 2 && !strcmp(argv[1], "--do-nothing")) {
exit(0);
}
if (!isdirectory("o/third_party/gcc")) {
system("third_party/gcc/unbundle.sh");
}
cc = argv[1];
if (!strchr(cc, '/')) {
if (!(cc = commandv(argv[1], ccpath))) exit(127);
}
ccversion = atoi(firstnonnull(emptytonull(getenv("CCVERSION")), "4"));
isgcc = strstr(basename(cc), "gcc");
isclang = strstr(basename(cc), "clang");
iscc = isgcc | isclang;
for (i = 1; i < argc; ++i) {
if (argv[i][0] != '-') {
AddFlag(argv[i]);
continue;
}
if (!strcmp(argv[i], "-o")) {
AddFlag(argv[i]);
AddFlag((outpath = argv[++i]));
continue;
}
if (iscc) {
AddFlag(argv[i]);
continue;
}
if (!strcmp(argv[i], "-w")) {
AddFlag(argv[i]);
AddFlag("-D__W__");
} else if (!strcmp(argv[i], "-Oz")) {
if (isclang) {
AddFlag(argv[i]);
} else {
AddFlag("-Os");
}
} else if (!strcmp(argv[i], "-pg")) {
wantpg = true;
} else if (!strcmp(argv[i], "-x-no-pg")) {
wantnopg = true;
} else if (!strcmp(argv[i], "-mfentry")) {
wantfentry = true;
} else if (!strcmp(argv[i], "-mnop-mcount")) {
wantnop = true;
} else if (!strcmp(argv[i], "-mrecord-mcount")) {
wantrecord = true;
} else if (!strcmp(argv[i], "-fno-omit-frame-pointer")) {
wantframe = true;
} else if (!strcmp(argv[i], "-fomit-frame-pointer")) {
wantframe = false;
} else if (!strcmp(argv[i], "-mno-vzeroupper")) {
if (isgcc) {
AddFlag("-Wa,-msse2avx");
AddFlag("-D__MNO_VZEROUPPER__");
} else if (isclang) {
AddFlag("-mllvm");
AddFlag("-x86-use-vzeroupper=0");
}
} else if (!strcmp(argv[i], "-msse2avx")) {
if (isgcc) {
AddFlag(argv[i]);
} else if (isclang) {
AddFlag("-Wa,-msse2avx");
}
} else if (!strcmp(argv[i], "-fsanitize=address")) {
if (isgcc && ccversion >= 6) wantasan = true;
} else if (!strcmp(argv[i], "-fsanitize=undefined")) {
if (isgcc && ccversion >= 6) wantubsan = true;
} else if (!strcmp(argv[i], "-fno-sanitize=address")) {
wantasan = false;
} else if (!strcmp(argv[i], "-fno-sanitize=undefined")) {
wantubsan = false;
} else if (!strcmp(argv[i], "-fno-sanitize=all")) {
wantasan = false;
wantubsan = false;
} else if (startswith(argv[i], "-fsanitize=implicit") &&
strstr(argv[i], "integer")) {
if (isgcc) AddFlag(argv[i]);
} else if (startswith(argv[i], "-fvect-cost") ||
startswith(argv[i], "-mstringop") ||
startswith(argv[i], "-gz") ||
strstr(argv[i], "stack-protector") ||
strstr(argv[i], "sanitize") ||
startswith(argv[i], "-fvect-cost") ||
startswith(argv[i], "-fvect-cost")) {
if (isgcc && ccversion >= 6) {
AddFlag(argv[i]);
}
} else if (startswith(argv[i], "-fdiagnostic-color=")) {
colorflag = argv[i];
} else if (startswith(argv[i], "-R") ||
!strcmp(argv[i], "-fsave-optimization-record")) {
if (isclang) AddFlag(argv[i]);
} else if (isclang &&
(!strcmp(argv[i], "-gstabs") || !strcmp(argv[i], "-ftrapv") ||
!strcmp(argv[i], "-fsignaling-nans") ||
!strcmp(argv[i], "-fcx-limited-range") ||
!strcmp(argv[i], "-fno-fp-int-builtin-inexact") ||
!strcmp(argv[i], "-Wno-unused-but-set-variable") ||
!strcmp(argv[i], "-Wunsafe-loop-optimizations") ||
!strcmp(argv[i], "-mdispatch-scheduler") ||
!strcmp(argv[i], "-ftracer") ||
!strcmp(argv[i], "-frounding-math") ||
!strcmp(argv[i], "-fmerge-constants") ||
!strcmp(argv[i], "-fmodulo-sched") ||
!strcmp(argv[i], "-fopt-info-vec") ||
!strcmp(argv[i], "-fopt-info-vec-missed") ||
!strcmp(argv[i], "-fmodulo-sched-allow-regmoves") ||
!strcmp(argv[i], "-freschedule-modulo-scheduled-loops") ||
!strcmp(argv[i], "-fipa-pta") ||
!strcmp(argv[i], "-fsched2-use-superblocks") ||
!strcmp(argv[i], "-fbranch-target-load-optimize") ||
!strcmp(argv[i], "-fdelete-dead-exceptions") ||
!strcmp(argv[i], "-funsafe-loop-optimizations") ||
!strcmp(argv[i], "-mmitigate-rop") ||
!strcmp(argv[i], "-fno-align-jumps") ||
!strcmp(argv[i], "-fno-align-labels") ||
!strcmp(argv[i], "-fno-align-loops") ||
!strcmp(argv[i], "-fivopts") ||
!strcmp(argv[i], "-fschedule-insns") ||
!strcmp(argv[i], "-fno-semantic-interposition") ||
!strcmp(argv[i], "-mno-fentry") ||
!strcmp(argv[i], "-fversion-loops-for-strides") ||
!strcmp(argv[i], "-femit-struct-debug-baseonly") ||
!strcmp(argv[i], "-ftree-loop-vectorize") ||
!strcmp(argv[i], "-gdescribe-dies") ||
!strcmp(argv[i], "-flimit-function-alignment") ||
!strcmp(argv[i], "-ftree-loop-im") ||
!strcmp(argv[i], "-fno-instrument-functions") ||
!strcmp(argv[i], "-fstack-clash-protection") ||
!strcmp(argv[i], "-mfpmath=sse+387") ||
!strcmp(argv[i], "-Wa,--noexecstack") ||
!strcmp(argv[i], "-freg-struct-return") ||
!strcmp(argv[i], "-mcall-ms2sysv-xlogues") ||
startswith(argv[i], "-ffixed-") ||
startswith(argv[i], "-fcall-saved") ||
startswith(argv[i], "-fcall-used") ||
startswith(argv[i], "-fgcse-") ||
strstr(argv[i], "shrink-wrap") ||
strstr(argv[i], "schedule-insns2") ||
startswith(argv[i], "-fvect-cost-model=") ||
startswith(argv[i], "-fsimd-cost-model=") ||
startswith(argv[i], "-fopt-info") ||
startswith(argv[i], "-mstringop-strategy=") ||
startswith(argv[i], "-mpreferred-stack-boundary=") ||
strstr(argv[i], "gnu-unique") ||
startswith(argv[i], "-Wframe-larger-than=") ||
strstr(argv[i], "whole-program") ||
startswith(argv[i], "-Wa,--size-check=") ||
startswith(argv[i], "-Wa,--listing"))) {
/* ignore flag so clang won't whine */
} else {
AddFlag(argv[i]);
}
}
if (iscc) {
if (isclang) {
AddFlag("-fno-integrated-as");
AddFlag("-Wno-unused-command-line-argument");
AddFlag("-Wno-incompatible-pointer-types-discards-qualifiers");
}
AddFlag("-no-canonical-prefixes");
if (!IsTerminalInarticulate()) {
AddFlag(firstnonnull(colorflag, "-fdiagnostics-color=always"));
}
if (wantpg && !wantnopg) {
AddFlag("-pg");
AddFlag("-D__PG__");
if (wantnop && !isclang) {
AddFlag("-mnop-mcount");
AddFlag("-D__MNOP_MCOUNT__");
}
if (wantrecord) {
AddFlag("-mrecord-mcount");
AddFlag("-D__MRECORD_MCOUNT__");
}
if (wantfentry) {
AddFlag("-mfentry");
AddFlag("-D__MFENTRY__");
}
}
if (wantasan) {
AddFlag("-fsanitize=address");
AddFlag("-D__FSANITIZE_ADDRESS__");
}
if (wantubsan) {
AddFlag("-fsanitize=undefined");
AddFlag("-fno-data-sections");
}
}
AddFlag(NULL);
if (outpath) {
outdir = xdirname(outpath);
if (!isdirectory(outdir)) {
makedirs(outdir, 0755);
}
}
write(2, command.p, command.n);
sigfillset(&mask);
sigprocmask(SIG_BLOCK, &mask, &savemask);
if ((pid = vfork()) == -1) exit(errno);
if (!pid) {
sigprocmask(SIG_SETMASK, &savemask, NULL);
execv(cc, flags.p);
_exit(127);
}
while (waitpid(pid, &ws, 0) == -1) {
if (errno != EINTR) exit(errno);
}
if (WIFEXITED(ws)) {
return WEXITSTATUS(ws);
} else {
return 128 + WTERMSIG(ws);
}
}

View File

@ -174,7 +174,7 @@
(runs (format "o/$m/%s.com.runs TESTARGS=-b" name))
(buns (format "o/$m/test/%s_test.com.runs TESTARGS=-b" name)))
(cond ((not (member ext '("c" "cc" "s" "S" "rl" "f")))
(format "m=%s; make -j8 -O MODE=$m SILENT=0 o/$m/%s"
(format "m=%s; make -j8 -O MODE=$m V=1 o/$m/%s"
mode
(directory-file-name
(file-name-directory
@ -187,7 +187,7 @@
(file-exists-p (format "%s" buddy)))
(format (cosmo-join
" && "
'("m=%s; n=%s; make -j8 -O o/$m/$n%s.o MODE=$m SILENT=0"
'("m=%s; n=%s; make -j8 -O o/$m/$n%s.o MODE=$m V=1"
;; "bloat o/$m/%s.o | head"
;; "nm -C --size o/$m/%s.o | sort -r"
"echo"
@ -199,7 +199,7 @@
(cosmo-join
" && "
`("m=%s; f=o/$m/%s.com"
,(concat "make -j8 -O $f MODE=$m SILENT=0")
,(concat "make -j8 -O $f MODE=$m V=1")
"./$f"))
mode name))
((and (file-regular-p this)
@ -210,7 +210,7 @@
(cosmo-join
" && "
`("m=%s; f=o/$m/%s%s.o"
,(concat "make -j8 -O $f MODE=$m SILENT=0")
,(concat "make -j8 -O $f MODE=$m V=1")
;; "nm -C --size $f | sort -r"
"echo"
"size -A $f | grep '^[.T]' | grep -v 'debug\\|command.line\\|stack' | sort -rnk2"
@ -419,7 +419,7 @@
(error "don't know how to show assembly for non c/c++ source file"))
(let* ((default-directory root)
(compile-command
(format "make %s SILENT=0 -j8 -O MODE=%s %s %s"
(format "make %s V=1 -j8 -O MODE=%s %s %s"
(or extra-make-flags "") mode asm-gcc asm-clang)))
(save-buffer)
(set-visited-file-modtime (current-time))
@ -440,8 +440,8 @@
;; -ffast-math -funsafe-math-optimizations -fsched2-use-superblocks -fjump-tables
(cond ((not (eq 0 (logand 8 arg)))
(cosmo--assembly (setq arg (logand (lognot 8)))
"SILENT=0 OVERRIDE_COPTS='-fverbose-asm -fsanitize=address'"))
(t (cosmo--assembly arg "SILENT=0 OVERRIDE_COPTS='' CPPFLAGS='-DSTACK_FRAME_UNLIMITED'"))))
"V=1 OVERRIDE_COPTS='-fverbose-asm -fsanitize=address'"))
(t (cosmo--assembly arg "V=1 OVERRIDE_COPTS='' CPPFLAGS='-DSTACK_FRAME_UNLIMITED'"))))
(defun cosmo-assembly-native (arg)
(interactive "P")
@ -449,11 +449,11 @@
(cond ((not (eq 0 (logand 8 arg)))
(cosmo--assembly
(setq arg (logand (lognot 8)))
"SILENT=0 CCFLAGS=--verbose COPTS='$(IEEE_MATH)' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=k8'")) ;; znver2
"V=1 CCFLAGS=--verbose COPTS='$(IEEE_MATH)' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=k8'")) ;; znver2
(t
(cosmo--assembly
arg
"SILENT=0 CCFLAGS=--verbose COPTS='$(MATHEMATICAL) -O3' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=k8'")))) ;; znver2
"V=1 CCFLAGS=--verbose COPTS='$(MATHEMATICAL) -O3' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=k8'")))) ;; znver2
(defun cosmo-assembly-icelake (arg)
(interactive "P")
@ -461,15 +461,15 @@
(cond ((not (eq 0 (logand 8 arg)))
(cosmo--assembly
(setq arg (logand (lognot 8)))
"SILENT=0 CCFLAGS=--verbose COPTS='$(MATHEMATICAL) -O3' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=icelake-client'"))
"V=1 CCFLAGS=--verbose COPTS='$(MATHEMATICAL) -O3' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=icelake-client'"))
(t
(cosmo--assembly
arg
"SILENT=0 CCFLAGS=--verbose COPTS='$(MATHEMATICAL) -O3' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=icelake-client'"))))
"V=1 CCFLAGS=--verbose COPTS='$(MATHEMATICAL) -O3' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' TARGET_ARCH='-march=icelake-client'"))))
(defun cosmo-assembly-balanced (arg)
(interactive "P")
(cosmo--assembly (or arg 5) "CFLAGS='-O2 -ftrapv' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' SILENT=0"))
(cosmo--assembly (or arg 5) "CFLAGS='-O2 -ftrapv' CPPFLAGS='-DSTACK_FRAME_UNLIMITED' V=1"))
(defun cosmo-mca (arg)
(interactive "P")

104
tool/viz/bf.c Normal file
View File

@ -0,0 +1,104 @@
/*-*- 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/fmt/itoa.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/str/tpenc.h"
#include "libc/sysv/consts/o.h"
/**
* @fileoverview BingFold - A Hexdump Tool
*/
#define W 64
#define C 253
void bf(int fd) {
ssize_t rc;
uint64_t w;
int c, fg, fg2;
size_t i, n, o;
char ibuf[W], obuf[12 + 1 + W * 6 + 1 + W * (2 + 11) + 11 + 1];
o = 0;
do {
if ((rc = read(fd, ibuf, W)) == -1) exit(2);
if (rc) {
n = 0;
n += uint64toarray_fixed16(o, obuf + n, 48);
o += rc;
obuf[n++] = ' ';
for (i = 0; i < rc; ++i) {
c = ibuf[i] & 0xff;
w = tpenc(kCp437[c]);
do {
obuf[n++] = w;
} while ((w >>= 8));
}
for (i = 0; i < W - rc + 1; ++i) {
obuf[n++] = ' ';
}
for (fg = -1, i = 0; i < rc; ++i) {
c = ibuf[i] & 0xff;
if (c < 32) {
fg2 = 237 + c * ((C - 237) / 32.);
} else if (c >= 232) {
fg2 = C + (c - 232) * ((255 - C) / (256. - 232));
} else {
fg2 = C;
}
if (fg2 != fg) {
fg = fg2;
obuf[n++] = '\e';
obuf[n++] = '[';
obuf[n++] = '3';
obuf[n++] = '8';
obuf[n++] = ';';
obuf[n++] = '5';
obuf[n++] = ';';
n += int64toarray_radix10(o, obuf + n);
obuf[n++] = 'm';
}
obuf[n++] = "0123456789abcdef"[c >> 4];
obuf[n++] = "0123456789abcdef"[c & 15];
/* obuf[n++] = ' '; */
}
obuf[n++] = '\e';
obuf[n++] = '[';
obuf[n++] = '0';
obuf[n++] = 'm';
obuf[n++] = '\n';
write(1, obuf, n);
}
} while (rc == W);
}
int main(int argc, char *argv[]) {
int i, fd;
if (argc > 1) {
for (i = 1; i < argc; ++i) {
if (i > 1) write(1, "\n", 1);
if ((fd = open(argv[i], O_RDONLY)) == -1) exit(1);
bf(fd);
}
} else {
bf(0);
}
return 0;
}

View File

@ -46,21 +46,23 @@
EXPECT_MATRIXEQ_(__FILE__, __LINE__, __FUNCTION__, YN, XN, M, #M, WANT, \
StringifyMatrixShort, NULL, NULL, NULL)
#define EXPECT_MATRIXEQ_(FILE, LINE, FUNC, YN, XN, M, MC, WANT, F, ...) \
do { \
char *Got; \
const char *Want; \
Want = (WANT); \
Got = F(YN, XN, M, FormatStringTableForAssertion, __VA_ARGS__); \
if (testlib_strequals(sizeof(char), Want, Got)) { \
testlib_free(Got); \
} else { \
TESTLIB_ONFAIL(FILE, FUNC); \
TESTLIB_SHOWERROR(testlib_showerror_expect_matrixeq, LINE, "...", MC, \
testlib_formatstr(sizeof(char), Want, -1), \
testlib_formatstr(sizeof(char), Got, -1), ""); \
} \
#define EXPECT_MATRIXEQ_(FILE, LINE, FUNC, YN, XN, M, MC, WANT, F, ...) \
do { \
char *Got; \
const char *Want; \
Want = (WANT); \
Got = F(YN, XN, M, FormatStringTableForAssertion, __VA_ARGS__); \
if (testlib_strequals(sizeof(char), Want, Got)) { \
testlib_free(Got); \
} else { \
testlib_showerror_expect_matrixeq( \
LINE, "...", MC, testlib_formatstr(sizeof(char), Want, -1), \
testlib_formatstr(sizeof(char), Got, -1), ""); \
} \
} while (0)
void testlib_showerror_expect_matrixeq(int, const char *, const char *, char *,
char *, const char *, ...);
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_TOOL_VIZ_LIB_FORMATSTRINGTABLE_TESTLIB_H_ */