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_ */