diff options
author | June McEnroe <june@causal.agency> | 2018-05-13 00:41:58 -0400 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2018-05-13 00:42:28 -0400 |
commit | 869f6622bbb883257a0eb96742752b9969cfb0be (patch) | |
tree | 7d2b2ff7b0c4dd5395bfc23585d27fe9052802a9 | |
parent | Tabify shell scripts (diff) | |
download | src-869f6622bbb883257a0eb96742752b9969cfb0be.tar.gz src-869f6622bbb883257a0eb96742752b9969cfb0be.zip |
Tabify bin
-rw-r--r-- | bin/bri.c | 84 | ||||
-rw-r--r-- | bin/brot.c | 152 | ||||
-rw-r--r-- | bin/dtch.c | 320 | ||||
-rw-r--r-- | bin/fbatt.c | 168 | ||||
-rw-r--r-- | bin/fbclock.c | 184 | ||||
-rw-r--r-- | bin/gfx/cocoa.m | 196 | ||||
-rw-r--r-- | bin/gfx/fb.c | 76 | ||||
-rw-r--r-- | bin/gfx/none.c | 2 | ||||
-rw-r--r-- | bin/gfx/x11.c | 158 | ||||
-rw-r--r-- | bin/gfxx.c | 692 | ||||
-rw-r--r-- | bin/glitch.c | 674 | ||||
-rw-r--r-- | bin/hnel.c | 154 | ||||
-rw-r--r-- | bin/klon.c | 484 | ||||
-rw-r--r-- | bin/pbd.c | 152 | ||||
-rw-r--r-- | bin/pngo.c | 1056 | ||||
-rw-r--r-- | bin/scheme.c | 290 | ||||
-rw-r--r-- | bin/wake.c | 38 | ||||
-rw-r--r-- | bin/watch.c | 100 | ||||
-rw-r--r-- | bin/xx.c | 170 |
19 files changed, 2575 insertions, 2575 deletions
diff --git a/bin/bri.c b/bin/bri.c index 413958c5..561b22df 100644 --- a/bin/bri.c +++ b/bin/bri.c @@ -26,58 +26,58 @@ static const char *CLASS = "/sys/class/backlight"; int main(int argc, char *argv[]) { - int error; + int error; - const char *input = (argc > 1) ? argv[1] : NULL; + const char *input = (argc > 1) ? argv[1] : NULL; - error = chdir(CLASS); - if (error) err(EX_OSFILE, "%s", CLASS); + error = chdir(CLASS); + if (error) err(EX_OSFILE, "%s", CLASS); - DIR *dir = opendir("."); - if (!dir) err(EX_OSFILE, "%s", CLASS); + DIR *dir = opendir("."); + if (!dir) err(EX_OSFILE, "%s", CLASS); - struct dirent *entry; - while (NULL != (errno = 0, entry = readdir(dir))) { - if (entry->d_name[0] == '.') continue; + struct dirent *entry; + while (NULL != (errno = 0, entry = readdir(dir))) { + if (entry->d_name[0] == '.') continue; - error = chdir(entry->d_name); - if (error) err(EX_OSFILE, "%s/%s", CLASS, entry->d_name); - break; - } - if (!entry) { - if (errno) err(EX_IOERR, "%s", CLASS); - errx(EX_CONFIG, "%s: empty", CLASS); - } + error = chdir(entry->d_name); + if (error) err(EX_OSFILE, "%s/%s", CLASS, entry->d_name); + break; + } + if (!entry) { + if (errno) err(EX_IOERR, "%s", CLASS); + errx(EX_CONFIG, "%s: empty", CLASS); + } - FILE *actual = fopen("actual_brightness", "r"); - if (!actual) err(EX_OSFILE, "%s/actual_brightness", CLASS); + FILE *actual = fopen("actual_brightness", "r"); + if (!actual) err(EX_OSFILE, "%s/actual_brightness", CLASS); - unsigned value; - int match = fscanf(actual, "%u", &value); - if (match == EOF) err(EX_IOERR, "%s/actual_brightness", CLASS); - if (match < 1) errx(EX_DATAERR, "%s/actual_brightness", CLASS); + unsigned value; + int match = fscanf(actual, "%u", &value); + if (match == EOF) err(EX_IOERR, "%s/actual_brightness", CLASS); + if (match < 1) errx(EX_DATAERR, "%s/actual_brightness", CLASS); - if (!input) { - printf("%u\n", value); - return EX_OK; - } + if (!input) { + printf("%u\n", value); + return EX_OK; + } - if (input[0] == '+' || input[0] == '-') { - size_t count = strnlen(input, 16); - if (input[0] == '+') { - value += 16 * count; - } else { - value -= 16 * count; - } - } else { - value = strtoul(input, NULL, 0); - } + if (input[0] == '+' || input[0] == '-') { + size_t count = strnlen(input, 16); + if (input[0] == '+') { + value += 16 * count; + } else { + value -= 16 * count; + } + } else { + value = strtoul(input, NULL, 0); + } - FILE *brightness = fopen("brightness", "w"); - if (!brightness) err(EX_OSFILE, "%s/brightness", CLASS); + FILE *brightness = fopen("brightness", "w"); + if (!brightness) err(EX_OSFILE, "%s/brightness", CLASS); - int size = fprintf(brightness, "%u", value); - if (size < 0) err(EX_IOERR, "brightness"); + int size = fprintf(brightness, "%u", value); + if (size < 0) err(EX_IOERR, "brightness"); - return EX_OK; + return EX_OK; } diff --git a/bin/brot.c b/bin/brot.c index 09ca9c4b..f487c236 100644 --- a/bin/brot.c +++ b/bin/brot.c @@ -32,18 +32,18 @@ #define GRAY(n) RGB(n, n, n) static double absSq(double complex z) { - return creal(z) * creal(z) + cimag(z) * cimag(z); + return creal(z) * creal(z) + cimag(z) * cimag(z); } static uint32_t depth = 50; static uint32_t mandelbrot(double complex c) { - double complex z = 0; - for (uint32_t i = 0; i < depth; ++i) { - if (absSq(z) > 4.0) return i; - z = z * z + c; - } - return 0; + double complex z = 0; + for (uint32_t i = 0; i < depth; ++i) { + if (absSq(z) > 4.0) return i; + z = z * z + c; + } + return 0; } static double complex translate = -0.75; @@ -52,34 +52,34 @@ static double complex transform = 2.5; static uint32_t samples = 1; static void sample(uint32_t *buf, size_t width, size_t height) { - double yRatio = (height > width) ? (double)height / (double)width : 1.0; - double xRatio = (width > height) ? (double)width / (double)height : 1.0; - - memset(buf, 0, 4 * width * height); - size_t superWidth = width * samples; - size_t superHeight = height * samples; - for (size_t y = 0; y < superHeight; ++y) { - for (size_t x = 0; x < superWidth; ++x) { - double zx = (((double)x + 0.5) / (double)superWidth - 0.5) * xRatio; - double zy = (((double)y + 0.5) / (double)superHeight - 0.5) * yRatio; - uint32_t n = mandelbrot((zx + zy * I) * transform + translate); - buf[(y / samples) * width + (x / samples)] += n; - } - } + double yRatio = (height > width) ? (double)height / (double)width : 1.0; + double xRatio = (width > height) ? (double)width / (double)height : 1.0; + + memset(buf, 0, 4 * width * height); + size_t superWidth = width * samples; + size_t superHeight = height * samples; + for (size_t y = 0; y < superHeight; ++y) { + for (size_t x = 0; x < superWidth; ++x) { + double zx = (((double)x + 0.5) / (double)superWidth - 0.5) * xRatio; + double zy = (((double)y + 0.5) / (double)superHeight - 0.5) * yRatio; + uint32_t n = mandelbrot((zx + zy * I) * transform + translate); + buf[(y / samples) * width + (x / samples)] += n; + } + } } static void color(uint32_t *buf, size_t width, size_t height) { - for (size_t i = 0; i < width * height; ++i) { - buf[i] = GRAY(255 * buf[i] / samples / samples / depth); - } + for (size_t i = 0; i < width * height; ++i) { + buf[i] = GRAY(255 * buf[i] / samples / samples / depth); + } } static double frameTime; void draw(uint32_t *buf, size_t width, size_t height) { - clock_t t0 = clock(); - sample(buf, width, height); - color(buf, width, height); - frameTime = (double)(clock() - t0) / (double)CLOCKS_PER_SEC; + clock_t t0 = clock(); + sample(buf, width, height); + color(buf, width, height); + frameTime = (double)(clock() - t0) / (double)CLOCKS_PER_SEC; } static double translateStep = 1.0 / 128.0; @@ -87,61 +87,61 @@ static double rotateStep = 1.0 / 128.0; static double scaleStep = 1.0 / 32.0; bool input(char in) { - const double PI = acos(-1.0); - switch (in) { - case 'q': return false; - break; case '.': depth++; - break; case ',': if (depth > 1) depth--; - break; case 'l': translate += translateStep * transform; - break; case 'h': translate -= translateStep * transform; - break; case 'j': translate += translateStep * I * transform; - break; case 'k': translate -= translateStep * I * transform; - break; case 'u': transform *= cexp(rotateStep * PI * I); - break; case 'i': transform /= cexp(rotateStep * PI * I); - break; case '+': transform *= 1.0 - scaleStep; - break; case '-': transform /= 1.0 - scaleStep; - break; case '0': translate = -0.75; transform = 2.5; - break; case ']': samples++; - break; case '[': if (samples > 1) samples--; - } - return true; + const double PI = acos(-1.0); + switch (in) { + case 'q': return false; + break; case '.': depth++; + break; case ',': if (depth > 1) depth--; + break; case 'l': translate += translateStep * transform; + break; case 'h': translate -= translateStep * transform; + break; case 'j': translate += translateStep * I * transform; + break; case 'k': translate -= translateStep * I * transform; + break; case 'u': transform *= cexp(rotateStep * PI * I); + break; case 'i': transform /= cexp(rotateStep * PI * I); + break; case '+': transform *= 1.0 - scaleStep; + break; case '-': transform /= 1.0 - scaleStep; + break; case '0': translate = -0.75; transform = 2.5; + break; case ']': samples++; + break; case '[': if (samples > 1) samples--; + } + return true; } const char *status(void) { - static char buf[256]; - snprintf( - buf, sizeof(buf), - "brot -s %u -i %u -t %g%+gi -f %g%+gi # %.6f", - samples, depth, - creal(translate), cimag(translate), - creal(transform), cimag(transform), - frameTime - ); - return buf; + static char buf[256]; + snprintf( + buf, sizeof(buf), + "brot -s %u -i %u -t %g%+gi -f %g%+gi # %.6f", + samples, depth, + creal(translate), cimag(translate), + creal(transform), cimag(transform), + frameTime + ); + return buf; } static double complex parseComplex(const char *str) { - double real = 0.0, imag = 0.0; - real = strtod(str, (char **)&str); - if (str[0] == 'i') { - imag = real; - real = 0.0; - } else if (str[0]) { - imag = strtod(str, NULL); - } - return real + imag * I; + double real = 0.0, imag = 0.0; + real = strtod(str, (char **)&str); + if (str[0] == 'i') { + imag = real; + real = 0.0; + } else if (str[0]) { + imag = strtod(str, NULL); + } + return real + imag * I; } int init(int argc, char *argv[]) { - int opt; - while (0 < (opt = getopt(argc, argv, "f:i:s:t:"))) { - switch (opt) { - case 'f': transform = parseComplex(optarg); break; - case 'i': depth = strtoul(optarg, NULL, 0); break; - case 's': samples = strtoul(optarg, NULL, 0); break; - case 't': translate = parseComplex(optarg); break; - default: return EX_USAGE; - } - } - return EX_OK; + int opt; + while (0 < (opt = getopt(argc, argv, "f:i:s:t:"))) { + switch (opt) { + case 'f': transform = parseComplex(optarg); break; + case 'i': depth = strtoul(optarg, NULL, 0); break; + case 's': samples = strtoul(optarg, NULL, 0); break; + case 't': translate = parseComplex(optarg); break; + default: return EX_USAGE; + } + } + return EX_OK; } diff --git a/bin/dtch.c b/bin/dtch.c index 7ec71801..fa97fdcc 100644 --- a/bin/dtch.c +++ b/bin/dtch.c @@ -40,208 +40,208 @@ #endif static struct passwd *getUser(void) { - uid_t uid = getuid(); - struct passwd *user = getpwuid(uid); - if (!user) err(EX_OSFILE, "/etc/passwd"); - return user; + uid_t uid = getuid(); + struct passwd *user = getpwuid(uid); + if (!user) err(EX_OSFILE, "/etc/passwd"); + return user; } static struct sockaddr_un sockAddr(const char *home, const char *name) { - struct sockaddr_un addr = { .sun_family = AF_LOCAL }; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/.dtch/%s", home, name); - return addr; + struct sockaddr_un addr = { .sun_family = AF_LOCAL }; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/.dtch/%s", home, name); + return addr; } static char z; static struct iovec iov = { .iov_base = &z, .iov_len = 1 }; static ssize_t sendFd(int sock, int fd) { - size_t size = CMSG_LEN(sizeof(int)); - char buf[size]; - struct msghdr msg = { - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = buf, - .msg_controllen = size, - }; - - struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = size; - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - *(int *)CMSG_DATA(cmsg) = fd; - - return sendmsg(sock, &msg, 0); + size_t size = CMSG_LEN(sizeof(int)); + char buf[size]; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = buf, + .msg_controllen = size, + }; + + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = size; + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *(int *)CMSG_DATA(cmsg) = fd; + + return sendmsg(sock, &msg, 0); } static int recvFd(int sock) { - size_t size = CMSG_LEN(sizeof(int)); - char buf[size]; - struct msghdr msg = { - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = buf, - .msg_controllen = size, - }; - - ssize_t n = recvmsg(sock, &msg, 0); - if (n < 0) return -1; - - struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); - if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS) { - errno = ENOMSG; - return -1; - } - - return *(int *)CMSG_DATA(cmsg); + size_t size = CMSG_LEN(sizeof(int)); + char buf[size]; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = buf, + .msg_controllen = size, + }; + + ssize_t n = recvmsg(sock, &msg, 0); + if (n < 0) return -1; + + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + if (!cmsg || cmsg->cmsg_type != SCM_RIGHTS) { + errno = ENOMSG; + return -1; + } + + return *(int *)CMSG_DATA(cmsg); } static struct sockaddr_un addr; static void unlinkAddr(void) { - unlink(addr.sun_path); + unlink(addr.sun_path); } static int dtch(int argc, char *argv[]) { - int error; + int error; - const struct passwd *user = getUser(); + const struct passwd *user = getUser(); - const char *name = user->pw_name; - if (argc > 1) { - name = argv[1]; - argv++; - argc--; - } - if (argc > 1) { - argv++; - } else { - argv[0] = user->pw_shell; - } + const char *name = user->pw_name; + if (argc > 1) { + name = argv[1]; + argv++; + argc--; + } + if (argc > 1) { + argv++; + } else { + argv[0] = user->pw_shell; + } - int home = open(user->pw_dir, 0); - if (home < 0) err(EX_CANTCREAT, "%s", user->pw_dir); + int home = open(user->pw_dir, 0); + if (home < 0) err(EX_CANTCREAT, "%s", user->pw_dir); - error = mkdirat(home, ".dtch", 0700); - if (error && errno != EEXIST) err(EX_CANTCREAT, "%s/.dtch", user->pw_dir); + error = mkdirat(home, ".dtch", 0700); + if (error && errno != EEXIST) err(EX_CANTCREAT, "%s/.dtch", user->pw_dir); - close(home); + close(home); - int server = socket(PF_LOCAL, SOCK_STREAM, 0); - if (server < 0) err(EX_OSERR, "socket"); + int server = socket(PF_LOCAL, SOCK_STREAM, 0); + if (server < 0) err(EX_OSERR, "socket"); - addr = sockAddr(user->pw_dir, name); - error = bind(server, (struct sockaddr *)&addr, sizeof(addr)); - if (error) err(EX_CANTCREAT, "%s", addr.sun_path); - fcntl(server, F_SETFD, FD_CLOEXEC); - atexit(unlinkAddr); + addr = sockAddr(user->pw_dir, name); + error = bind(server, (struct sockaddr *)&addr, sizeof(addr)); + if (error) err(EX_CANTCREAT, "%s", addr.sun_path); + fcntl(server, F_SETFD, FD_CLOEXEC); + atexit(unlinkAddr); - int pty; - pid_t pid = forkpty(&pty, NULL, NULL, NULL); - if (pid < 0) err(EX_OSERR, "forkpty"); + int pty; + pid_t pid = forkpty(&pty, NULL, NULL, NULL); + if (pid < 0) err(EX_OSERR, "forkpty"); - if (!pid) { - execvp(*argv, argv); - err(EX_NOINPUT, "%s", *argv); - } + if (!pid) { + execvp(*argv, argv); + err(EX_NOINPUT, "%s", *argv); + } - error = listen(server, 0); - if (error) err(EX_OSERR, "listen"); + error = listen(server, 0); + if (error) err(EX_OSERR, "listen"); - for (;;) { - int client = accept(server, NULL, NULL); - if (client < 0) err(EX_IOERR, "accept"); + for (;;) { + int client = accept(server, NULL, NULL); + if (client < 0) err(EX_IOERR, "accept"); - ssize_t size = sendFd(client, pty); - if (size < 0) warn("sendmsg"); + ssize_t size = sendFd(client, pty); + if (size < 0) warn("sendmsg"); - size = recv(client, &z, sizeof(z), 0); - if (size < 0) warn("recv"); + size = recv(client, &z, sizeof(z), 0); + if (size < 0) warn("recv"); - close(client); + close(client); - int status; - pid_t dead = waitpid(pid, &status, WNOHANG); - if (dead < 0) err(EX_OSERR, "waitpid(%d)", pid); - if (dead) return WIFEXITED(status) ? WEXITSTATUS(status) : EX_SOFTWARE; - } + int status; + pid_t dead = waitpid(pid, &status, WNOHANG); + if (dead < 0) err(EX_OSERR, "waitpid(%d)", pid); + if (dead) return WIFEXITED(status) ? WEXITSTATUS(status) : EX_SOFTWARE; + } } static struct termios saveTerm; static void restoreTerm(void) { - tcsetattr(STDIN_FILENO, TCSADRAIN, &saveTerm); - printf( - "\x1b[?1049l" // rmcup - "\x1b\x63\x1b[!p\x1b[?3;4l\x1b[4l\x1b>" // reset - ); + tcsetattr(STDIN_FILENO, TCSADRAIN, &saveTerm); + printf( + "\x1b[?1049l" // rmcup + "\x1b\x63\x1b[!p\x1b[?3;4l\x1b[4l\x1b>" // reset + ); } static int atch(int argc, char *argv[]) { - int error; - - const struct passwd *user = getUser(); - const char *name = (argc > 1) ? argv[1] : user->pw_name; - - int client = socket(PF_LOCAL, SOCK_STREAM, 0); - if (client < 0) err(EX_OSERR, "socket"); - - struct sockaddr_un addr = sockAddr(user->pw_dir, name); - error = connect(client, (struct sockaddr *)&addr, sizeof(addr)); - if (error) err(EX_NOINPUT, "%s", addr.sun_path); - - int pty = recvFd(client); - if (pty < 0) err(EX_IOERR, "recvmsg"); - - struct winsize window; - error = ioctl(STDIN_FILENO, TIOCGWINSZ, &window); - if (error) err(EX_IOERR, "TIOCGWINSZ"); - - struct winsize redraw = { .ws_row = 1, .ws_col = 1 }; - error = ioctl(pty, TIOCSWINSZ, &redraw); - if (error) err(EX_IOERR, "TIOCSWINSZ"); - - error = ioctl(pty, TIOCSWINSZ, &window); - if (error) err(EX_IOERR, "TIOCSWINSZ"); - - error = tcgetattr(STDIN_FILENO, &saveTerm); - if (error) err(EX_IOERR, "tcgetattr"); - atexit(restoreTerm); - - struct termios raw; - cfmakeraw(&raw); - error = tcsetattr(STDIN_FILENO, TCSADRAIN, &raw); - if (error) err(EX_IOERR, "tcsetattr"); - - char buf[4096]; - struct pollfd fds[2] = { - { .fd = STDIN_FILENO, .events = POLLIN }, - { .fd = pty, .events = POLLIN }, - }; - while (0 < poll(fds, 2, -1)) { - if (fds[0].revents) { - ssize_t size = read(STDIN_FILENO, buf, sizeof(buf)); - if (size < 0) err(EX_IOERR, "read(%d)", STDIN_FILENO); - - if (size == 1 && buf[0] == CTRL('Q')) return EX_OK; - - size = write(pty, buf, size); - if (size < 0) err(EX_IOERR, "write(%d)", pty); - } - - if (fds[1].revents) { - ssize_t size = read(pty, buf, sizeof(buf)); - if (size < 0) err(EX_IOERR, "read(%d)", pty); - - size = write(STDOUT_FILENO, buf, size); - if (size < 0) err(EX_IOERR, "write(%d)", STDOUT_FILENO); - } - } - err(EX_IOERR, "poll"); + int error; + + const struct passwd *user = getUser(); + const char *name = (argc > 1) ? argv[1] : user->pw_name; + + int client = socket(PF_LOCAL, SOCK_STREAM, 0); + if (client < 0) err(EX_OSERR, "socket"); + + struct sockaddr_un addr = sockAddr(user->pw_dir, name); + error = connect(client, (struct sockaddr *)&addr, sizeof(addr)); + if (error) err(EX_NOINPUT, "%s", addr.sun_path); + + int pty = recvFd(client); + if (pty < 0) err(EX_IOERR, "recvmsg"); + + struct winsize window; + error = ioctl(STDIN_FILENO, TIOCGWINSZ, &window); + if (error) err(EX_IOERR, "TIOCGWINSZ"); + + struct winsize redraw = { .ws_row = 1, .ws_col = 1 }; + error = ioctl(pty, TIOCSWINSZ, &redraw); + if (error) err(EX_IOERR, "TIOCSWINSZ"); + + error = ioctl(pty, TIOCSWINSZ, &window); + if (error) err(EX_IOERR, "TIOCSWINSZ"); + + error = tcgetattr(STDIN_FILENO, &saveTerm); + if (error) err(EX_IOERR, "tcgetattr"); + atexit(restoreTerm); + + struct termios raw; + cfmakeraw(&raw); + error = tcsetattr(STDIN_FILENO, TCSADRAIN, &raw); + if (error) err(EX_IOERR, "tcsetattr"); + + char buf[4096]; + struct pollfd fds[2] = { + { .fd = STDIN_FILENO, .events = POLLIN }, + { .fd = pty, .events = POLLIN }, + }; + while (0 < poll(fds, 2, -1)) { + if (fds[0].revents) { + ssize_t size = read(STDIN_FILENO, buf, sizeof(buf)); + if (size < 0) err(EX_IOERR, "read(%d)", STDIN_FILENO); + + if (size == 1 && buf[0] == CTRL('Q')) return EX_OK; + + size = write(pty, buf, size); + if (size < 0) err(EX_IOERR, "write(%d)", pty); + } + + if (fds[1].revents) { + ssize_t size = read(pty, buf, sizeof(buf)); + if (size < 0) err(EX_IOERR, "read(%d)", pty); + + size = write(STDOUT_FILENO, buf, size); + if (size < 0) err(EX_IOERR, "write(%d)", STDOUT_FILENO); + } + } + err(EX_IOERR, "poll"); } int main(int argc, char *argv[]) { - switch (argv[0][0]) { - case 'd': return dtch(argc, argv); - case 'a': return atch(argc, argv); - default: return EX_USAGE; - } + switch (argv[0][0]) { + case 'd': return dtch(argc, argv); + case 'a': return atch(argc, argv); + default: return EX_USAGE; + } } diff --git a/bin/fbatt.c b/bin/fbatt.c index 30714e2c..3486ba59 100644 --- a/bin/fbatt.c +++ b/bin/fbatt.c @@ -40,88 +40,88 @@ static const uint32_t YELLOW = 0xA37720; static const uint32_t RED = 0xA32810; int main() { - int error; - - DIR *dir = opendir(CLASS); - if (!dir) err(EX_OSFILE, "%s", CLASS); - - FILE *chargeFull = NULL; - FILE *chargeNow = NULL; - - const struct dirent *entry; - while (NULL != (errno = 0, entry = readdir(dir))) { - if (entry->d_name[0] == '.') continue; - - error = chdir(CLASS); - if (error) err(EX_OSFILE, "%s", CLASS); - - error = chdir(entry->d_name); - if (error) err(EX_OSFILE, "%s/%s", CLASS, entry->d_name); - - chargeFull = fopen("charge_full", "r"); - chargeNow = fopen("charge_now", "r"); - if (chargeFull && chargeNow) break; - } - if (!chargeFull || !chargeNow) { - if (errno) err(EX_OSFILE, "%s", CLASS); - errx(EX_CONFIG, "%s: empty", CLASS); - } - closedir(dir); - - const char *path = getenv("FRAMEBUFFER"); - if (!path) path = "/dev/fb0"; - - int fb = open(path, O_RDWR); - if (fb < 0) err(EX_OSFILE, "%s", path); - - struct fb_var_screeninfo info; - error = ioctl(fb, FBIOGET_VSCREENINFO, &info); - if (error) err(EX_IOERR, "%s", path); - - size_t size = 4 * info.xres * info.yres; - uint32_t *buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); - if (buf == MAP_FAILED) err(EX_IOERR, "%s", path); - - for (;;) { - int match; - - rewind(chargeFull); - fflush(chargeFull); - uint32_t full; - match = fscanf(chargeFull, "%u", &full); - if (match == EOF) err(EX_IOERR, "charge_full"); - if (match < 1) errx(EX_DATAERR, "charge_full"); - - rewind(chargeNow); - fflush(chargeNow); - uint32_t now; - match = fscanf(chargeNow, "%u", &now); - if (match == EOF) err(EX_IOERR, "charge_now"); - if (match < 1) errx(EX_DATAERR, "charge_now"); - - uint32_t percent = 100 * now / full; - uint32_t height = 16 * now / full; - - for (int i = 0; i < 60; ++i, sleep(1)) { - uint32_t left = info.xres - RIGHT - WIDTH; - - for (uint32_t y = 0; y <= HEIGHT; ++y) { - buf[y * info.xres + left - 1] = BORDER; - buf[y * info.xres + left + WIDTH] = BORDER; - } - for (uint32_t x = left; x < left + WIDTH; ++x) { - buf[HEIGHT * info.xres + x] = BORDER; - } - - for (uint32_t y = 0; y < HEIGHT; ++y) { - for (uint32_t x = left; x < left + WIDTH; ++x) { - buf[y * info.xres + x] = - (HEIGHT - 1 - y > height) ? BG - : (percent <= 10) ? RED - : (percent <= 30) ? YELLOW - : GRAY; - } - } - } - } + int error; + + DIR *dir = opendir(CLASS); + if (!dir) err(EX_OSFILE, "%s", CLASS); + + FILE *chargeFull = NULL; + FILE *chargeNow = NULL; + + const struct dirent *entry; + while (NULL != (errno = 0, entry = readdir(dir))) { + if (entry->d_name[0] == '.') continue; + + error = chdir(CLASS); + if (error) err(EX_OSFILE, "%s", CLASS); + + error = chdir(entry->d_name); + if (error) err(EX_OSFILE, "%s/%s", CLASS, entry->d_name); + + chargeFull = fopen("charge_full", "r"); + chargeNow = fopen("charge_now", "r"); + if (chargeFull && chargeNow) break; + } + if (!chargeFull || !chargeNow) { + if (errno) err(EX_OSFILE, "%s", CLASS); + errx(EX_CONFIG, "%s: empty", CLASS); + } + closedir(dir); + + const char *path = getenv("FRAMEBUFFER"); + if (!path) path = "/dev/fb0"; + + int fb = open(path, O_RDWR); + if (fb < 0) err(EX_OSFILE, "%s", path); + + struct fb_var_screeninfo info; + error = ioctl(fb, FBIOGET_VSCREENINFO, &info); + if (error) err(EX_IOERR, "%s", path); + + size_t size = 4 * info.xres * info.yres; + uint32_t *buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); + if (buf == MAP_FAILED) err(EX_IOERR, "%s", path); + + for (;;) { + int match; + + rewind(chargeFull); + fflush(chargeFull); + uint32_t full; + match = fscanf(chargeFull, "%u", &full); + if (match == EOF) err(EX_IOERR, "charge_full"); + if (match < 1) errx(EX_DATAERR, "charge_full"); + + rewind(chargeNow); + fflush(chargeNow); + uint32_t now; + match = fscanf(chargeNow, "%u", &now); + if (match == EOF) err(EX_IOERR, "charge_now"); + if (match < 1) errx(EX_DATAERR, "charge_now"); + + uint32_t percent = 100 * now / full; + uint32_t height = 16 * now / full; + + for (int i = 0; i < 60; ++i, sleep(1)) { + uint32_t left = info.xres - RIGHT - WIDTH; + + for (uint32_t y = 0; y <= HEIGHT; ++y) { + buf[y * info.xres + left - 1] = BORDER; + buf[y * info.xres + left + WIDTH] = BORDER; + } + for (uint32_t x = left; x < left + WIDTH; ++x) { + buf[HEIGHT * info.xres + x] = BORDER; + } + + for (uint32_t y = 0; y < HEIGHT; ++y) { + for (uint32_t x = left; x < left + WIDTH; ++x) { + buf[y * info.xres + x] = + (HEIGHT - 1 - y > height) ? BG + : (percent <= 10) ? RED + : (percent <= 30) ? YELLOW + : GRAY; + } + } + } + } } diff --git a/bin/fbclock.c b/bin/fbclock.c index bd967307..699ce969 100644 --- a/bin/fbclock.c +++ b/bin/fbclock.c @@ -30,102 +30,102 @@ static const uint32_t PSF2_MAGIC = 0x864AB572; struct Psf2Header { - uint32_t magic; - uint32_t version; - uint32_t headerSize; - uint32_t flags; - uint32_t glyphCount; - uint32_t glyphSize; - uint32_t glyphHeight; - uint32_t glyphWidth; + uint32_t magic; + uint32_t version; + uint32_t headerSize; + uint32_t flags; + uint32_t glyphCount; + uint32_t glyphSize; + uint32_t glyphHeight; + uint32_t glyphWidth; }; static const uint32_t BG = 0x161510; static const uint32_t FG = 0x7A7155; int main() { - size_t len; - - const char *fontPath = getenv("FONT"); - if (!fontPath) { - fontPath = "/usr/share/kbd/consolefonts/Lat2-Terminus16.psfu.gz"; - } - - gzFile font = gzopen(fontPath, "r"); - if (!font) err(EX_NOINPUT, "%s", fontPath); - - struct Psf2Header header; - len = gzfread(&header, sizeof(header), 1, font); - if (!len && gzeof(font)) errx(EX_DATAERR, "%s: missing header", fontPath); - if (!len) errx(EX_IOERR, "%s", gzerror(font, NULL)); - - if (header.magic != PSF2_MAGIC) { - errx( - EX_DATAERR, "%s: invalid header magic %08X", - fontPath, header.magic - ); - } - if (header.headerSize != sizeof(struct Psf2Header)) { - errx( - EX_DATAERR, "%s: weird header size %d", - fontPath, header.headerSize - ); - } - - uint8_t glyphs[128][header.glyphSize]; - len = gzfread(glyphs, header.glyphSize, 128, font); - if (!len && gzeof(font)) errx(EX_DATAERR, "%s: missing glyphs", fontPath); - if (!len) errx(EX_IOERR, "%s", gzerror(font, NULL)); - - gzclose(font); - - const char *fbPath = getenv("FRAMEBUFFER"); - if (!fbPath) fbPath = "/dev/fb0"; - - int fb = open(fbPath, O_RDWR); - if (fb < 0) err(EX_OSFILE, "%s", fbPath); - - struct fb_var_screeninfo info; - int error = ioctl(fb, FBIOGET_VSCREENINFO, &info); - if (error) err(EX_IOERR, "%s", fbPath); - - size_t size = 4 * info.xres * info.yres; - uint32_t *buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); - if (buf == MAP_FAILED) err(EX_IOERR, "%s", fbPath); - - for (;;) { - time_t t = time(NULL); - if (t < 0) err(EX_OSERR, "time"); - const struct tm *local = localtime(&t); - if (!local) err(EX_OSERR, "localtime"); - - char str[64]; - len = strftime(str, sizeof(str), "%H:%M", local); - assert(len); - - for (int i = 0; i < (60 - local->tm_sec); ++i, sleep(1)) { - uint32_t left = info.xres - header.glyphWidth * len; - uint32_t bottom = header.glyphHeight; - - for (uint32_t y = 0; y < bottom; ++y) { - buf[y * info.xres + left - 1] = FG; - } - for (uint32_t x = left - 1; x < info.xres; ++x) { - buf[bottom * info.xres + x] = FG; - } - - for (const char *s = str; *s; ++s) { - const uint8_t *glyph = glyphs[(unsigned)*s]; - uint32_t stride = header.glyphSize / header.glyphHeight; - for (uint32_t y = 0; y < header.glyphHeight; ++y) { - for (uint32_t x = 0; x < header.glyphWidth; ++x) { - uint8_t bits = glyph[y * stride + x / 8]; - uint8_t bit = bits >> (7 - x % 8) & 1; - buf[y * info.xres + left + x] = bit ? FG : BG; - } - } - left += header.glyphWidth; - } - } - } + size_t len; + + const char *fontPath = getenv("FONT"); + if (!fontPath) { + fontPath = "/usr/share/kbd/consolefonts/Lat2-Terminus16.psfu.gz"; + } + + gzFile font = gzopen(fontPath, "r"); + if (!font) err(EX_NOINPUT, "%s", fontPath); + + struct Psf2Header header; + len = gzfread(&header, sizeof(header), 1, font); + if (!len && gzeof(font)) errx(EX_DATAERR, "%s: missing header", fontPath); + if (!len) errx(EX_IOERR, "%s", gzerror(font, NULL)); + + if (header.magic != PSF2_MAGIC) { + errx( + EX_DATAERR, "%s: invalid header magic %08X", + fontPath, header.magic + ); + } + if (header.headerSize != sizeof(struct Psf2Header)) { + errx( + EX_DATAERR, "%s: weird header size %d", + fontPath, header.headerSize + ); + } + + uint8_t glyphs[128][header.glyphSize]; + len = gzfread(glyphs, header.glyphSize, 128, font); + if (!len && gzeof(font)) errx(EX_DATAERR, "%s: missing glyphs", fontPath); + if (!len) errx(EX_IOERR, "%s", gzerror(font, NULL)); + + gzclose(font); + + const char *fbPath = getenv("FRAMEBUFFER"); + if (!fbPath) fbPath = "/dev/fb0"; + + int fb = open(fbPath, O_RDWR); + if (fb < 0) err(EX_OSFILE, "%s", fbPath); + + struct fb_var_screeninfo info; + int error = ioctl(fb, FBIOGET_VSCREENINFO, &info); + if (error) err(EX_IOERR, "%s", fbPath); + + size_t size = 4 * info.xres * info.yres; + uint32_t *buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); + if (buf == MAP_FAILED) err(EX_IOERR, "%s", fbPath); + + for (;;) { + time_t t = time(NULL); + if (t < 0) err(EX_OSERR, "time"); + const struct tm *local = localtime(&t); + if (!local) err(EX_OSERR, "localtime"); + + char str[64]; + len = strftime(str, sizeof(str), "%H:%M", local); + assert(len); + + for (int i = 0; i < (60 - local->tm_sec); ++i, sleep(1)) { + uint32_t left = info.xres - header.glyphWidth * len; + uint32_t bottom = header.glyphHeight; + + for (uint32_t y = 0; y < bottom; ++y) { + buf[y * info.xres + left - 1] = FG; + } + for (uint32_t x = left - 1; x < info.xres; ++x) { + buf[bottom * info.xres + x] = FG; + } + + for (const char *s = str; *s; ++s) { + const uint8_t *glyph = glyphs[(unsigned)*s]; + uint32_t stride = header.glyphSize / header.glyphHeight; + for (uint32_t y = 0; y < header.glyphHeight; ++y) { + for (uint32_t x = 0; x < header.glyphWidth; ++x) { + uint8_t bits = glyph[y * stride + x / 8]; + uint8_t bit = bits >> (7 - x % 8) & 1; + buf[y * info.xres + left + x] = bit ? FG : BG; + } + } + left += header.glyphWidth; + } + } + } } diff --git a/bin/gfx/cocoa.m b/bin/gfx/cocoa.m index 495b1f9f..3df6c62a 100644 --- a/bin/gfx/cocoa.m +++ b/bin/gfx/cocoa.m @@ -26,78 +26,78 @@ #define UNUSED __attribute__((unused)) @interface BufferView : NSView { - size_t bufSize; - uint32_t *buf; - CGColorSpaceRef colorSpace; - CGDataProviderRef dataProvider; + size_t bufSize; + uint32_t *buf; + CGColorSpaceRef colorSpace; + CGDataProviderRef dataProvider; } @end @implementation BufferView - (instancetype) initWithFrame: (NSRect) frameRect { - colorSpace = CGColorSpaceCreateDeviceRGB(); - return [super initWithFrame: frameRect]; + colorSpace = CGColorSpaceCreateDeviceRGB(); + return [super initWithFrame: frameRect]; } - (void) setWindowTitle { - [[self window] setTitle: [NSString stringWithUTF8String: status()]]; + [[self window] setTitle: [NSString stringWithUTF8String: status()]]; } - (void) draw { - draw(buf, [self frame].size.width, [self frame].size.height); - [self setNeedsDisplay: YES]; + draw(buf, [self frame].size.width, [self frame].size.height); + [self setNeedsDisplay: YES]; } - (void) setFrameSize: (NSSize) newSize { - [super setFrameSize: newSize]; - size_t newBufSize = 4 * newSize.width * newSize.height; - if (newBufSize > bufSize) { - bufSize = newBufSize; - buf = malloc(bufSize); - if (!buf) err(EX_OSERR, "malloc(%zu)", bufSize); - CGDataProviderRelease(dataProvider); - dataProvider = CGDataProviderCreateWithData(NULL, buf, bufSize, NULL); - } - [self draw]; + [super setFrameSize: newSize]; + size_t newBufSize = 4 * newSize.width * newSize.height; + if (newBufSize > bufSize) { + bufSize = newBufSize; + buf = malloc(bufSize); + if (!buf) err(EX_OSERR, "malloc(%zu)", bufSize); + CGDataProviderRelease(dataProvider); + dataProvider = CGDataProviderCreateWithData(NULL, buf, bufSize, NULL); + } + [self draw]; } - (void) drawRect: (NSRect) UNUSED dirtyRect { - NSSize size = [self frame].size; - CGContextRef ctx = [[NSGraphicsContext currentContext] CGContext]; - CGImageRef image = CGImageCreate( - size.width, size.height, - 8, 32, 4 * size.width, - colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, - dataProvider, - NULL, false, kCGRenderingIntentDefault - ); - CGContextDrawImage(ctx, [self frame], image); - CGImageRelease(image); + NSSize size = [self frame].size; + CGContextRef ctx = [[NSGraphicsContext currentContext] CGContext]; + CGImageRef image = CGImageCreate( + size.width, size.height, + 8, 32, 4 * size.width, + colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst, + dataProvider, + NULL, false, kCGRenderingIntentDefault + ); + CGContextDrawImage(ctx, [self frame], image); + CGImageRelease(image); } - (BOOL) acceptsFirstResponder { - return YES; + return YES; } - (void) keyDown: (NSEvent *) event { - char in; - BOOL converted = [ - [event characters] - getBytes: &in - maxLength: 1 - usedLength: NULL - encoding: NSASCIIStringEncoding - options: 0 - range: NSMakeRange(0, 1) - remainingRange: NULL - ]; - if (converted) { - if (!input(in)) { - [NSApp terminate: self]; - } - [self draw]; - [self setWindowTitle]; - } + char in; + BOOL converted = [ + [event characters] + getBytes: &in + maxLength: 1 + usedLength: NULL + encoding: NSASCIIStringEncoding + options: 0 + range: NSMakeRange(0, 1) + remainingRange: NULL + ]; + if (converted) { + if (!input(in)) { + [NSApp terminate: self]; + } + [self draw]; + [self setWindowTitle]; + } } @end @@ -106,57 +106,57 @@ @implementation Delegate - (BOOL) applicationShouldTerminateAfterLastWindowClosed: - (NSApplication *) UNUSED sender { - return YES; + (NSApplication *) UNUSED sender { + return YES; } @end int main(int argc, char *argv[]) { - int error = init(argc, argv); - if (error) return error; - - [NSApplication sharedApplication]; - [NSApp setActivationPolicy: NSApplicationActivationPolicyRegular]; - [NSApp setDelegate: [Delegate new]]; - - NSString *name = [[NSProcessInfo processInfo] processName]; - NSMenu *menu = [NSMenu new]; - [ - menu - addItemWithTitle: @"Close Window" - action: @selector(performClose:) - keyEquivalent: @"w" - ]; - [menu addItem: [NSMenuItem separatorItem]]; - [ - menu - addItemWithTitle: [@"Quit " stringByAppendingString: name] - action: @selector(terminate:) - keyEquivalent: @"q" - ]; - NSMenuItem *menuItem = [NSMenuItem new]; - [menuItem setSubmenu: menu]; - [NSApp setMainMenu: [NSMenu new]]; - [[NSApp mainMenu] addItem: menuItem]; - - NSUInteger style = NSTitledWindowMask - | NSClosableWindowMask - | NSMiniaturizableWindowMask - | NSResizableWindowMask; - NSWindow *window = [ - [NSWindow alloc] - initWithContentRect: NSMakeRect(0, 0, 800, 600) - styleMask: style - backing: NSBackingStoreBuffered - defer: YES - ]; - [window center]; - - BufferView *view = [[BufferView alloc] initWithFrame: [window frame]]; - [window setContentView: view]; - [view setWindowTitle]; - - [window makeKeyAndOrderFront: nil]; - [NSApp activateIgnoringOtherApps: YES]; - [NSApp run]; + int error = init(argc, argv); + if (error) return error; + + [NSApplication sharedApplication]; + [NSApp setActivationPolicy: NSApplicationActivationPolicyRegular]; + [NSApp setDelegate: [Delegate new]]; + + NSString *name = [[NSProcessInfo processInfo] processName]; + NSMenu *menu = [NSMenu new]; + [ + menu + addItemWithTitle: @"Close Window" + action: @selector(performClose:) + keyEquivalent: @"w" + ]; + [menu addItem: [NSMenuItem separatorItem]]; + [ + menu + addItemWithTitle: [@"Quit " stringByAppendingString: name] + action: @selector(terminate:) + keyEquivalent: @"q" + ]; + NSMenuItem *menuItem = [NSMenuItem new]; + [menuItem setSubmenu: menu]; + [NSApp setMainMenu: [NSMenu new]]; + [[NSApp mainMenu] addItem: menuItem]; + + NSUInteger style = NSTitledWindowMask + | NSClosableWindowMask + | NSMiniaturizableWindowMask + | NSResizableWindowMask; + NSWindow *window = [ + [NSWindow alloc] + initWithContentRect: NSMakeRect(0, 0, 800, 600) + styleMask: style + backing: NSBackingStoreBuffered + defer: YES + ]; + [window center]; + + BufferView *view = [[BufferView alloc] initWithFrame: [window frame]]; + [window setContentView: view]; + [view setWindowTitle]; + + [window makeKeyAndOrderFront: nil]; + [NSApp activateIgnoringOtherApps: YES]; + [NSApp run]; } diff --git a/bin/gfx/fb.c b/bin/gfx/fb.c index 651ed80c..e1ef5e82 100644 --- a/bin/gfx/fb.c +++ b/bin/gfx/fb.c @@ -32,56 +32,56 @@ static struct termios saveTerm; static void restoreTerm(void) { - tcsetattr(STDERR_FILENO, TCSADRAIN, &saveTerm); + tcsetattr(STDERR_FILENO, TCSADRAIN, &saveTerm); } int main(int argc, char *argv[]) { - int error; + int error; - error = init(argc, argv); - if (error) return error; + error = init(argc, argv); + if (error) return error; - const char *path = getenv("FRAMEBUFFER"); - if (!path) path = "/dev/fb0"; + const char *path = getenv("FRAMEBUFFER"); + if (!path) path = "/dev/fb0"; - int fb = open(path, O_RDWR); - if (fb < 0) err(EX_OSFILE, "%s", path); + int fb = open(path, O_RDWR); + if (fb < 0) err(EX_OSFILE, "%s", path); - struct fb_var_screeninfo info; - error = ioctl(fb, FBIOGET_VSCREENINFO, &info); - if (error) err(EX_IOERR, "%s", path); + struct fb_var_screeninfo info; + error = ioctl(fb, FBIOGET_VSCREENINFO, &info); + if (error) err(EX_IOERR, "%s", path); - size_t size = 4 * info.xres * info.yres; - uint32_t *buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); - if (buf == MAP_FAILED) err(EX_IOERR, "%s", path); + size_t size = 4 * info.xres * info.yres; + uint32_t *buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); + if (buf == MAP_FAILED) err(EX_IOERR, "%s", path); - error = tcgetattr(STDERR_FILENO, &saveTerm); - if (error) err(EX_IOERR, "tcgetattr"); - atexit(restoreTerm); + error = tcgetattr(STDERR_FILENO, &saveTerm); + if (error) err(EX_IOERR, "tcgetattr"); + atexit(restoreTerm); - struct termios term = saveTerm; - term.c_lflag &= ~(ICANON | ECHO); - error = tcsetattr(STDERR_FILENO, TCSADRAIN, &term); - if (error) err(EX_IOERR, "tcsetattr"); + struct termios term = saveTerm; + term.c_lflag &= ~(ICANON | ECHO); + error = tcsetattr(STDERR_FILENO, TCSADRAIN, &term); + if (error) err(EX_IOERR, "tcsetattr"); - uint32_t saveBg = buf[0]; + uint32_t saveBg = buf[0]; - uint32_t back[info.xres * info.yres]; - for (;;) { - draw(back, info.xres, info.yres); - memcpy(buf, back, size); + uint32_t back[info.xres * info.yres]; + for (;;) { + draw(back, info.xres, info.yres); + memcpy(buf, back, size); - char in; - ssize_t len = read(STDERR_FILENO, &in, 1); - if (len < 0) err(EX_IOERR, "read"); - if (!len) return EX_DATAERR; + char in; + ssize_t len = read(STDERR_FILENO, &in, 1); + if (len < 0) err(EX_IOERR, "read"); + if (!len) return EX_DATAERR; - if (!input(in)) { - for (uint32_t i = 0; i < info.xres * info.yres; ++i) { - buf[i] = saveBg; - } - fprintf(stderr, "%s\n", status()); - return EX_OK; - } - } + if (!input(in)) { + for (uint32_t i = 0; i < info.xres * info.yres; ++i) { + buf[i] = saveBg; + } + fprintf(stderr, "%s\n", status()); + return EX_OK; + } + } } diff --git a/bin/gfx/none.c b/bin/gfx/none.c index e5d53a9b..31de2ff4 100644 --- a/bin/gfx/none.c +++ b/bin/gfx/none.c @@ -20,5 +20,5 @@ #include "gfx.h" int main() { - errx(EX_CONFIG, "no gfx frontend"); + errx(EX_CONFIG, "no gfx frontend"); } diff --git a/bin/gfx/x11.c b/bin/gfx/x11.c index 82d5c833..eae926c2 100644 --- a/bin/gfx/x11.c +++ b/bin/gfx/x11.c @@ -40,96 +40,96 @@ static size_t pixmapHeight; static Pixmap pixmap; static void createWindow(void) { - display = XOpenDisplay(NULL); - if (!display) errx(EX_UNAVAILABLE, "XOpenDisplay: %s", XDisplayName(NULL)); + display = XOpenDisplay(NULL); + if (!display) errx(EX_UNAVAILABLE, "XOpenDisplay: %s", XDisplayName(NULL)); - Window root = DefaultRootWindow(display); - window = XCreateSimpleWindow(display, root, 0, 0, width, height, 0, 0, 0); + Window root = DefaultRootWindow(display); + window = XCreateSimpleWindow(display, root, 0, 0, width, height, 0, 0, 0); - WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", false); - XSetWMProtocols(display, window, &WM_DELETE_WINDOW, 1); + WM_DELETE_WINDOW = XInternAtom(display, "WM_DELETE_WINDOW", false); + XSetWMProtocols(display, window, &WM_DELETE_WINDOW, 1); - windowGc = XCreateGC(display, window, 0, NULL); + windowGc = XCreateGC(display, window, 0, NULL); - image = XCreateImage(display, NULL, 24, ZPixmap, 0, NULL, width, height, 32, 0); + image = XCreateImage(display, NULL, 24, ZPixmap, 0, NULL, width, height, 32, 0); } static void resizePixmap(void) { - size_t newSize = 4 * width * height; - if (newSize > bufSize) { - bufSize = newSize; - free(buf); - buf = malloc(bufSize); - if (!buf) err(EX_OSERR, "malloc(%zu)", bufSize); - } - - image->data = (char *)buf; - image->width = width; - image->height = height; - image->bytes_per_line = 4 * width; - - if (width > pixmapWidth || height > pixmapHeight) { - pixmapWidth = width; - pixmapHeight = height; - if (pixmap) XFreePixmap(display, pixmap); - pixmap = XCreatePixmap(display, window, pixmapWidth, pixmapHeight, 24); - } + size_t newSize = 4 * width * height; + if (newSize > bufSize) { + bufSize = newSize; + free(buf); + buf = malloc(bufSize); + if (!buf) err(EX_OSERR, "malloc(%zu)", bufSize); + } + + image->data = (char *)buf; + image->width = width; + image->height = height; + image->bytes_per_line = 4 * width; + + if (width > pixmapWidth || height > pixmapHeight) { + pixmapWidth = width; + pixmapHeight = height; + if (pixmap) XFreePixmap(display, pixmap); + pixmap = XCreatePixmap(display, window, pixmapWidth, pixmapHeight, 24); + } } static void drawWindow(void) { - draw(buf, width, height); - XPutImage(display, pixmap, windowGc, image, 0, 0, 0, 0, width, height); - XCopyArea(display, pixmap, window, windowGc, 0, 0, width, height, 0, 0); + draw(buf, width, height); + XPutImage(display, pixmap, windowGc, image, 0, 0, 0, 0, width, height); + XCopyArea(display, pixmap, window, windowGc, 0, 0, width, height, 0, 0); } int main(int argc, char *argv[]) { - int error = init(argc, argv); - if (error) return error; - - createWindow(); - resizePixmap(); - drawWindow(); - - XStoreName(display, window, status()); - XMapWindow(display, window); - - XEvent event; - XSelectInput(display, window, ExposureMask | StructureNotifyMask | KeyPressMask); - for (;;) { - XNextEvent(display, &event); - - switch (event.type) { - case KeyPress: { - XKeyEvent key = event.xkey; - KeySym sym = XLookupKeysym(&key, key.state & ShiftMask); - if (sym > 0x80) break; - if (!input(sym)) return EX_OK; - drawWindow(); - XStoreName(display, window, status()); - } break; - - case ConfigureNotify: { - XConfigureEvent configure = event.xconfigure; - width = configure.width; - height = configure.height; - resizePixmap(); - drawWindow(); - } break; - - case Expose: { - XExposeEvent expose = event.xexpose; - XCopyArea( - display, pixmap, window, windowGc, - expose.x, expose.y, - expose.width, expose.height, - expose.x, expose.y - ); - } break; - - case ClientMessage: { - XClientMessageEvent client = event.xclient; - if ((Atom)client.data.l[0] == WM_DELETE_WINDOW) return EX_OK; - } break; - } - } + int error = init(argc, argv); + if (error) return error; + + createWindow(); + resizePixmap(); + drawWindow(); + + XStoreName(display, window, status()); + XMapWindow(display, window); + + XEvent event; + XSelectInput(display, window, ExposureMask | StructureNotifyMask | KeyPressMask); + for (;;) { + XNextEvent(display, &event); + + switch (event.type) { + case KeyPress: { + XKeyEvent key = event.xkey; + KeySym sym = XLookupKeysym(&key, key.state & ShiftMask); + if (sym > 0x80) break; + if (!input(sym)) return EX_OK; + drawWindow(); + XStoreName(display, window, status()); + } break; + + case ConfigureNotify: { + XConfigureEvent configure = event.xconfigure; + width = configure.width; + height = configure.height; + resizePixmap(); + drawWindow(); + } break; + + case Expose: { + XExposeEvent expose = event.xexpose; + XCopyArea( + display, pixmap, window, windowGc, + expose.x, expose.y, + expose.width, expose.height, + expose.x, expose.y + ); + } break; + + case ClientMessage: { + XClientMessageEvent client = event.xclient; + if ((Atom)client.data.l[0] == WM_DELETE_WINDOW) return EX_OK; + } break; + } + } } diff --git a/bin/gfxx.c b/bin/gfxx.c index ebd53738..2a7eb36e 100644 --- a/bin/gfxx.c +++ b/bin/gfxx.c @@ -38,17 +38,17 @@ #define GRAY(n) RGB(n, n, n) static enum { - COLOR_INDEXED, - COLOR_GRAYSCALE, - COLOR_RGB, - COLOR__COUNT, + COLOR_INDEXED, + COLOR_GRAYSCALE, + COLOR_RGB, + COLOR__COUNT, } space = COLOR_RGB; static const char *COLOR__STR[COLOR__COUNT] = { "indexed", "grayscale", "rgb" }; static uint32_t palette[256]; static enum { - ENDIAN_LITTLE, - ENDIAN_BIG, + ENDIAN_LITTLE, + ENDIAN_BIG, } byteOrder, bitOrder; enum { PAD, R, G, B }; @@ -68,425 +68,425 @@ static size_t size; static uint8_t *data; int init(int argc, char *argv[]) { - const char *pal = NULL; - const char *path = NULL; - - int opt; - while (0 < (opt = getopt(argc, argv, "c:p:b:e:E:n:fmw:z:o:"))) { - switch (opt) { - case 'c': switch (optarg[0]) { - case 'i': space = COLOR_INDEXED; break; - case 'g': space = COLOR_GRAYSCALE; break; - case 'r': space = COLOR_RGB; break; - default: return EX_USAGE; - } break; - case 'p': pal = optarg; break; - case 'e': switch (optarg[0]) { - case 'l': byteOrder = ENDIAN_LITTLE; break; - case 'b': byteOrder = ENDIAN_BIG; break; - default: return EX_USAGE; - } break; - case 'E': switch (optarg[0]) { - case 'l': bitOrder = ENDIAN_LITTLE; break; - case 'b': bitOrder = ENDIAN_BIG; break; - default: return EX_USAGE; - } break; - case 'b': { - if (strlen(optarg) < 4) return EX_USAGE; - for (int i = 0; i < 4; ++i) { - bits[i] = optarg[i] - '0'; - } - } break; - case 'n': offset = strtoul(optarg, NULL, 0); break; - case 'f': flip ^= true; break; - case 'm': mirror ^= true; break; - case 'w': width = strtoul(optarg, NULL, 0); break; - case 'z': scale = strtoul(optarg, NULL, 0); break; - case 'o': prefix = optarg; break; - default: return EX_USAGE; - } - } - if (argc > optind) path = argv[optind]; - if (!width || !scale) return EX_USAGE; - - if (pal) { - FILE *file = fopen(pal, "r"); - if (!file) err(EX_NOINPUT, "%s", pal); - fread(palette, 4, 256, file); - if (ferror(file)) err(EX_IOERR, "%s", pal); - fclose(file); - } else { - for (int i = 0; i < 256; ++i) { - double h = i / 256.0 * 6.0; - double x = 1.0 - fabs(fmod(h, 2.0) - 1.0); - double r = 255.0, g = 255.0, b = 255.0; - if (h <= 1.0) { g *= x; b = 0.0; } - else if (h <= 2.0) { r *= x; b = 0.0; } - else if (h <= 3.0) { r = 0.0; b *= x; } - else if (h <= 4.0) { r = 0.0; g *= x; } - else if (h <= 5.0) { r *= x; g = 0.0; } - else if (h <= 6.0) { g = 0.0; b *= x; } - palette[i] = (uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b; - } - } - - if (path) { - int fd = open(path, O_RDONLY); - if (fd < 0) err(EX_NOINPUT, "%s", path); - - struct stat stat; - int error = fstat(fd, &stat); - if (error) err(EX_IOERR, "%s", path); - size = stat.st_size; - - data = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); - if (data == MAP_FAILED) err(EX_IOERR, "%s", path); - - } else { - size = 1024 * 1024; - data = malloc(size); - if (!data) err(EX_OSERR, "malloc(%zu)", size); - - size = fread(data, 1, size, stdin); - if (ferror(stdin)) err(EX_IOERR, "(stdin)"); - } - - return EX_OK; + const char *pal = NULL; + const char *path = NULL; + + int opt; + while (0 < (opt = getopt(argc, argv, "c:p:b:e:E:n:fmw:z:o:"))) { + switch (opt) { + case 'c': switch (optarg[0]) { + case 'i': space = COLOR_INDEXED; break; + case 'g': space = COLOR_GRAYSCALE; break; + case 'r': space = COLOR_RGB; break; + default: return EX_USAGE; + } break; + case 'p': pal = optarg; break; + case 'e': switch (optarg[0]) { + case 'l': byteOrder = ENDIAN_LITTLE; break; + case 'b': byteOrder = ENDIAN_BIG; break; + default: return EX_USAGE; + } break; + case 'E': switch (optarg[0]) { + case 'l': bitOrder = ENDIAN_LITTLE; break; + case 'b': bitOrder = ENDIAN_BIG; break; + default: return EX_USAGE; + } break; + case 'b': { + if (strlen(optarg) < 4) return EX_USAGE; + for (int i = 0; i < 4; ++i) { + bits[i] = optarg[i] - '0'; + } + } break; + case 'n': offset = strtoul(optarg, NULL, 0); break; + case 'f': flip ^= true; break; + case 'm': mirror ^= true; break; + case 'w': width = strtoul(optarg, NULL, 0); break; + case 'z': scale = strtoul(optarg, NULL, 0); break; + case 'o': prefix = optarg; break; + default: return EX_USAGE; + } + } + if (argc > optind) path = argv[optind]; + if (!width || !scale) return EX_USAGE; + + if (pal) { + FILE *file = fopen(pal, "r"); + if (!file) err(EX_NOINPUT, "%s", pal); + fread(palette, 4, 256, file); + if (ferror(file)) err(EX_IOERR, "%s", pal); + fclose(file); + } else { + for (int i = 0; i < 256; ++i) { + double h = i / 256.0 * 6.0; + double x = 1.0 - fabs(fmod(h, 2.0) - 1.0); + double r = 255.0, g = 255.0, b = 255.0; + if (h <= 1.0) { g *= x; b = 0.0; } + else if (h <= 2.0) { r *= x; b = 0.0; } + else if (h <= 3.0) { r = 0.0; b *= x; } + else if (h <= 4.0) { r = 0.0; g *= x; } + else if (h <= 5.0) { r *= x; g = 0.0; } + else if (h <= 6.0) { g = 0.0; b *= x; } + palette[i] = (uint32_t)r << 16 | (uint32_t)g << 8 | (uint32_t)b; + } + } + + if (path) { + int fd = open(path, O_RDONLY); + if (fd < 0) err(EX_NOINPUT, "%s", path); + + struct stat stat; + int error = fstat(fd, &stat); + if (error) err(EX_IOERR, "%s", path); + size = stat.st_size; + + data = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) err(EX_IOERR, "%s", path); + + } else { + size = 1024 * 1024; + data = malloc(size); + if (!data) err(EX_OSERR, "malloc(%zu)", size); + + size = fread(data, 1, size, stdin); + if (ferror(stdin)) err(EX_IOERR, "(stdin)"); + } + + return EX_OK; } static char options[128]; static void formatOptions(void) { - snprintf( - options, sizeof(options), - "gfxx -c %s -e%c -E%c -b %hhu%hhu%hhu%hhu -n 0x%zX %s%s-w %zu -z %zu", - COLOR__STR[space], - "lb"[byteOrder], - "lb"[bitOrder], - bits[PAD], bits[R], bits[G], bits[B], - offset, - flip ? "-f " : "", - mirror ? "-m " : "", - width, - scale - ); + snprintf( + options, sizeof(options), + "gfxx -c %s -e%c -E%c -b %hhu%hhu%hhu%hhu -n 0x%zX %s%s-w %zu -z %zu", + COLOR__STR[space], + "lb"[byteOrder], + "lb"[bitOrder], + bits[PAD], bits[R], bits[G], bits[B], + offset, + flip ? "-f " : "", + mirror ? "-m " : "", + width, + scale + ); } const char *status(void) { - formatOptions(); - return options; + formatOptions(); + return options; } struct Iter { - uint32_t *buf; - size_t bufWidth; - size_t bufHeight; - size_t left; - size_t x; - size_t y; + uint32_t *buf; + size_t bufWidth; + size_t bufHeight; + size_t left; + size_t x; + size_t y; }; static struct Iter iter(uint32_t *buf, size_t bufWidth, size_t bufHeight) { - struct Iter it = { .buf = buf, .bufWidth = bufWidth, .bufHeight = bufHeight }; - if (mirror) it.x = width - 1; - if (flip) it.y = bufHeight / scale - 1; - return it; + struct Iter it = { .buf = buf, .bufWidth = bufWidth, .bufHeight = bufHeight }; + if (mirror) it.x = width - 1; + if (flip) it.y = bufHeight / scale - 1; + return it; } static bool nextX(struct Iter *it) { - if (mirror) { - if (it->x == it->left) return false; - it->x--; - } else { - it->x++; - if (it->x == it->left + width) return false; - } - return true; + if (mirror) { + if (it->x == it->left) return false; + it->x--; + } else { + it->x++; + if (it->x == it->left + width) return false; + } + return true; } static bool nextY(struct Iter *it) { - if (flip) { - if (it->y == 0) { - it->left += width; - it->y = it->bufHeight / scale; - } - it->y--; - } else { - it->y++; - if (it->y == it->bufHeight / scale) { - it->left += width; - it->y = 0; - } - } - it->x = it->left; - if (mirror) it->x += width - 1; - return (it->left < it->bufWidth / scale); + if (flip) { + if (it->y == 0) { + it->left += width; + it->y = it->bufHeight / scale; + } + it->y--; + } else { + it->y++; + if (it->y == it->bufHeight / scale) { + it->left += width; + it->y = 0; + } + } + it->x = it->left; + if (mirror) it->x += width - 1; + return (it->left < it->bufWidth / scale); } static bool next(struct Iter *it) { - return nextX(it) || nextY(it); + return nextX(it) || nextY(it); } static void put(const struct Iter *it, uint32_t pixel) { - size_t scaledX = it->x * scale; - size_t scaledY = it->y * scale; - for (size_t fillY = scaledY; fillY < scaledY + scale; ++fillY) { - if (fillY >= it->bufHeight) break; - for (size_t fillX = scaledX; fillX < scaledX + scale; ++fillX) { - if (fillX >= it->bufWidth) break; - it->buf[fillY * it->bufWidth + fillX] = pixel; - } - } + size_t scaledX = it->x * scale; + size_t scaledY = it->y * scale; + for (size_t fillY = scaledY; fillY < scaledY + scale; ++fillY) { + if (fillY >= it->bufHeight) break; + for (size_t fillX = scaledX; fillX < scaledX + scale; ++fillX) { + if (fillX >= it->bufWidth) break; + it->buf[fillY * it->bufWidth + fillX] = pixel; + } + } } static uint8_t interp(uint8_t b, uint32_t n) { - if (b == 8) return n; - if (b == 0) return 0; - return n * MASK(8) / MASK(b); + if (b == 8) return n; + if (b == 0) return 0; + return n * MASK(8) / MASK(b); } static uint32_t interpolate(uint32_t rgb) { - uint32_t r, g, b; - if (bitOrder == ENDIAN_LITTLE) { - b = rgb & MASK(bits[B]); - g = (rgb >>= bits[B]) & MASK(bits[G]); - r = (rgb >>= bits[G]) & MASK(bits[R]); - } else { - r = rgb & MASK(bits[R]); - g = (rgb >>= bits[R]) & MASK(bits[G]); - b = (rgb >>= bits[G]) & MASK(bits[B]); - } - return RGB(interp(bits[R], r), interp(bits[G], g), interp(bits[B], b)); + uint32_t r, g, b; + if (bitOrder == ENDIAN_LITTLE) { + b = rgb & MASK(bits[B]); + g = (rgb >>= bits[B]) & MASK(bits[G]); + r = (rgb >>= bits[G]) & MASK(bits[R]); + } else { + r = rgb & MASK(bits[R]); + g = (rgb >>= bits[R]) & MASK(bits[G]); + b = (rgb >>= bits[G]) & MASK(bits[B]); + } + return RGB(interp(bits[R], r), interp(bits[G], g), interp(bits[B], b)); } static void drawBits(struct Iter *it) { - for (size_t i = offset; i < size; ++i) { - for (uint8_t b = 0; b < 8; b += BITS_TOTAL) { - uint8_t n; - if (byteOrder == ENDIAN_BIG) { - n = data[i] >> (8 - BITS_TOTAL - b) & MASK(BITS_TOTAL); - } else { - n = data[i] >> b & MASK(BITS_TOTAL); - } - - if (space == COLOR_INDEXED) { - put(it, palette[n]); - } else if (space == COLOR_GRAYSCALE) { - put(it, GRAY(interp(BITS_COLOR, n & MASK(BITS_COLOR)))); - } else if (space == COLOR_RGB) { - put(it, interpolate(n)); - } - - if (!next(it)) return; - } - } + for (size_t i = offset; i < size; ++i) { + for (uint8_t b = 0; b < 8; b += BITS_TOTAL) { + uint8_t n; + if (byteOrder == ENDIAN_BIG) { + n = data[i] >> (8 - BITS_TOTAL - b) & MASK(BITS_TOTAL); + } else { + n = data[i] >> b & MASK(BITS_TOTAL); + } + + if (space == COLOR_INDEXED) { + put(it, palette[n]); + } else if (space == COLOR_GRAYSCALE) { + put(it, GRAY(interp(BITS_COLOR, n & MASK(BITS_COLOR)))); + } else if (space == COLOR_RGB) { + put(it, interpolate(n)); + } + + if (!next(it)) return; + } + } } static void drawBytes(struct Iter *it) { - uint8_t bytes = (BITS_TOTAL + 7) / 8; - for (size_t i = offset; i + bytes <= size; i += bytes) { - uint32_t n = 0; - for (size_t b = 0; b < bytes; ++b) { - n <<= 8; - n |= (byteOrder == ENDIAN_BIG) ? data[i + b] : data[i + bytes - b - 1]; - } - - if (space == COLOR_INDEXED) { - put(it, palette[n & 0xFF]); - } else if (space == COLOR_GRAYSCALE) { - put(it, GRAY(interp(BITS_COLOR, n & MASK(BITS_COLOR)))); - } else if (space == COLOR_RGB) { - put(it, interpolate(n)); - } - - if (!next(it)) return; - } + uint8_t bytes = (BITS_TOTAL + 7) / 8; + for (size_t i = offset; i + bytes <= size; i += bytes) { + uint32_t n = 0; + for (size_t b = 0; b < bytes; ++b) { + n <<= 8; + n |= (byteOrder == ENDIAN_BIG) ? data[i + b] : data[i + bytes - b - 1]; + } + + if (space == COLOR_INDEXED) { + put(it, palette[n & 0xFF]); + } else if (space == COLOR_GRAYSCALE) { + put(it, GRAY(interp(BITS_COLOR, n & MASK(BITS_COLOR)))); + } else if (space == COLOR_RGB) { + put(it, interpolate(n)); + } + + if (!next(it)) return; + } } static struct { - unsigned counter; - char path[FILENAME_MAX]; - FILE *file; + unsigned counter; + char path[FILENAME_MAX]; + FILE *file; } out; static void outOpen(const char *ext) { - snprintf(out.path, sizeof(out.path), "%s%04u.%s", prefix, ++out.counter, ext); - out.file = fopen(out.path, "wx"); - if (out.file) { - printf("%s\n", out.path); - } else { - warn("%s", out.path); - } + snprintf(out.path, sizeof(out.path), "%s%04u.%s", prefix, ++out.counter, ext); + out.file = fopen(out.path, "wx"); + if (out.file) { + printf("%s\n", out.path); + } else { + warn("%s", out.path); + } } static uint32_t crc; static void pngWrite(const void *ptr, size_t size) { - fwrite(ptr, size, 1, out.file); - if (ferror(out.file)) err(EX_IOERR, "%s", out.path); - crc = crc32(crc, ptr, size); + fwrite(ptr, size, 1, out.file); + if (ferror(out.file)) err(EX_IOERR, "%s", out.path); + crc = crc32(crc, ptr, size); } static void pngUint(uint32_t host) { - uint32_t net = htonl(host); - pngWrite(&net, 4); + uint32_t net = htonl(host); + pngWrite(&net, 4); } static void pngChunk(const char *type, uint32_t size) { - pngUint(size); - crc = crc32(0, Z_NULL, 0); - pngWrite(type, 4); + pngUint(size); + crc = crc32(0, Z_NULL, 0); + pngWrite(type, 4); } static void pngDump(uint32_t *src, size_t srcWidth, size_t srcHeight) { - int error; - - size_t stride = 1 + 3 * srcWidth; - uint8_t data[stride * srcHeight]; - for (size_t y = 0; y < srcHeight; ++y) { - data[y * stride] = 0; - for (size_t x = 0; x < srcWidth; ++x) { - uint8_t *p = &data[y * stride + 1 + 3 * x]; - p[0] = src[y * srcWidth + x] >> 16; - p[1] = src[y * srcWidth + x] >> 8; - p[2] = src[y * srcWidth + x]; - } - } - - uLong deflateSize = compressBound(sizeof(data)); - uint8_t deflate[deflateSize]; - error = compress(deflate, &deflateSize, data, sizeof(data)); - if (error != Z_OK) errx(EX_SOFTWARE, "compress: %d", error); - - outOpen("png"); - if (!out.file) return; - - const uint8_t SIGNATURE[] = { 0x89, 'P', 'N', 'G', '\r', '\n', 0x1A, '\n' }; - const uint8_t HEADER[] = { 8, 2, 0, 0, 0 }; // 8-bit truecolor - const char SOFTWARE[] = "Software"; - formatOptions(); - uint8_t sbit[3] = { MAX(bits[R], 1), MAX(bits[G], 1), MAX(bits[B], 1) }; - - pngWrite(SIGNATURE, sizeof(SIGNATURE)); - - pngChunk("IHDR", 4 + 4 + sizeof(HEADER)); - pngUint(srcWidth); - pngUint(srcHeight); - pngWrite(HEADER, sizeof(HEADER)); - pngUint(crc); - - pngChunk("tEXt", sizeof(SOFTWARE) + strlen(options)); - pngWrite(SOFTWARE, sizeof(SOFTWARE)); - pngWrite(options, strlen(options)); - pngUint(crc); - - pngChunk("sBIT", sizeof(sbit)); - pngWrite(sbit, sizeof(sbit)); - pngUint(crc); - - pngChunk("IDAT", deflateSize); - pngWrite(deflate, deflateSize); - pngUint(crc); - - pngChunk("IEND", 0); - pngUint(crc); - - error = fclose(out.file); - if (error) err(EX_IOERR, "%s", out.path); + int error; + + size_t stride = 1 + 3 * srcWidth; + uint8_t data[stride * srcHeight]; + for (size_t y = 0; y < srcHeight; ++y) { + data[y * stride] = 0; + for (size_t x = 0; x < srcWidth; ++x) { + uint8_t *p = &data[y * stride + 1 + 3 * x]; + p[0] = src[y * srcWidth + x] >> 16; + p[1] = src[y * srcWidth + x] >> 8; + p[2] = src[y * srcWidth + x]; + } + } + + uLong deflateSize = compressBound(sizeof(data)); + uint8_t deflate[deflateSize]; + error = compress(deflate, &deflateSize, data, sizeof(data)); + if (error != Z_OK) errx(EX_SOFTWARE, "compress: %d", error); + + outOpen("png"); + if (!out.file) return; + + const uint8_t SIGNATURE[] = { 0x89, 'P', 'N', 'G', '\r', '\n', 0x1A, '\n' }; + const uint8_t HEADER[] = { 8, 2, 0, 0, 0 }; // 8-bit truecolor + const char SOFTWARE[] = "Software"; + formatOptions(); + uint8_t sbit[3] = { MAX(bits[R], 1), MAX(bits[G], 1), MAX(bits[B], 1) }; + + pngWrite(SIGNATURE, sizeof(SIGNATURE)); + + pngChunk("IHDR", 4 + 4 + sizeof(HEADER)); + pngUint(srcWidth); + pngUint(srcHeight); + pngWrite(HEADER, sizeof(HEADER)); + pngUint(crc); + + pngChunk("tEXt", sizeof(SOFTWARE) + strlen(options)); + pngWrite(SOFTWARE, sizeof(SOFTWARE)); + pngWrite(options, strlen(options)); + pngUint(crc); + + pngChunk("sBIT", sizeof(sbit)); + pngWrite(sbit, sizeof(sbit)); + pngUint(crc); + + pngChunk("IDAT", deflateSize); + pngWrite(deflate, deflateSize); + pngUint(crc); + + pngChunk("IEND", 0); + pngUint(crc); + + error = fclose(out.file); + if (error) err(EX_IOERR, "%s", out.path); } static enum { - DUMP_NONE, - DUMP_ONE, - DUMP_ALL, + DUMP_NONE, + DUMP_ONE, + DUMP_ALL, } dump; void draw(uint32_t *buf, size_t bufWidth, size_t bufHeight) { - memset(buf, 0, 4 * bufWidth * bufHeight); - struct Iter it = iter(buf, bufWidth, bufHeight); - if (BITS_TOTAL >= 8) { - drawBytes(&it); - } else { - drawBits(&it); - } - if (dump) pngDump(buf, bufWidth, bufHeight); - if (dump == DUMP_ONE) dump = DUMP_NONE; + memset(buf, 0, 4 * bufWidth * bufHeight); + struct Iter it = iter(buf, bufWidth, bufHeight); + if (BITS_TOTAL >= 8) { + drawBytes(&it); + } else { + drawBits(&it); + } + if (dump) pngDump(buf, bufWidth, bufHeight); + if (dump == DUMP_ONE) dump = DUMP_NONE; } static void palSample(void) { - size_t temp = scale; - scale = 1; - draw(palette, 256, 1); - scale = temp; + size_t temp = scale; + scale = 1; + draw(palette, 256, 1); + scale = temp; } static void palDump(void) { - outOpen("dat"); - if (!out.file) return; + outOpen("dat"); + if (!out.file) return; - fwrite(palette, 4, 256, out.file); - if (ferror(out.file)) err(EX_IOERR, "%s", out.path); + fwrite(palette, 4, 256, out.file); + if (ferror(out.file)) err(EX_IOERR, "%s", out.path); - int error = fclose(out.file); - if (error) err(EX_IOERR, "%s", out.path); + int error = fclose(out.file); + if (error) err(EX_IOERR, "%s", out.path); } static const uint8_t PRESETS[][4] = { - { 0, 0, 1, 0 }, - { 0, 1, 1, 0 }, - { 1, 1, 1, 1 }, - { 2, 2, 2, 2 }, - { 0, 3, 3, 2 }, - { 4, 4, 4, 4 }, - { 1, 5, 5, 5 }, - { 0, 5, 6, 5 }, - { 0, 8, 8, 8 }, - { 8, 8, 8, 8 }, + { 0, 0, 1, 0 }, + { 0, 1, 1, 0 }, + { 1, 1, 1, 1 }, + { 2, 2, 2, 2 }, + { 0, 3, 3, 2 }, + { 4, 4, 4, 4 }, + { 1, 5, 5, 5 }, + { 0, 5, 6, 5 }, + { 0, 8, 8, 8 }, + { 8, 8, 8, 8 }, }; #define PRESETS_LEN (sizeof(PRESETS) / sizeof(PRESETS[0])) static uint8_t preset = PRESETS_LEN - 1; static void setPreset(void) { - bits[PAD] = PRESETS[preset][PAD]; - bits[R] = PRESETS[preset][R]; - bits[G] = PRESETS[preset][G]; - bits[B] = PRESETS[preset][B]; + bits[PAD] = PRESETS[preset][PAD]; + bits[R] = PRESETS[preset][R]; + bits[G] = PRESETS[preset][G]; + bits[B] = PRESETS[preset][B]; } static void setBit(char in) { - static uint8_t bit = 0; - bits[bit++] = in - '0'; - bit &= 3; + static uint8_t bit = 0; + bits[bit++] = in - '0'; + bit &= 3; } bool input(char in) { - size_t pixel = (BITS_TOTAL + 7) / 8; - size_t row = width * BITS_TOTAL / 8; - switch (in) { - case 'q': return false; - break; case 'x': dump = DUMP_ONE; - break; case 'X': dump ^= DUMP_ALL; - break; case 'o': formatOptions(); printf("%s\n", options); - break; case '[': if (!space--) space = COLOR__COUNT - 1; - break; case ']': if (++space == COLOR__COUNT) space = 0; - break; case 'p': palSample(); - break; case 'P': palDump(); - break; case '{': if (!preset--) preset = PRESETS_LEN - 1; setPreset(); - break; case '}': if (++preset == PRESETS_LEN) preset = 0; setPreset(); - break; case 'e': byteOrder ^= ENDIAN_BIG; - break; case 'E': bitOrder ^= ENDIAN_BIG; - break; case 'h': if (offset) offset--; - break; case 'j': offset += pixel; - break; case 'k': if (offset >= pixel) offset -= pixel; - break; case 'l': offset++; - break; case 'H': if (offset >= row) offset -= row; - break; case 'J': offset += width * row; - break; case 'K': if (offset >= width * row) offset -= width * row; - break; case 'L': offset += row; - break; case '.': width++; - break; case ',': if (width > 1) width--; - break; case '>': width *= 2; - break; case '<': if (width > 1) width /= 2; - break; case 'f': flip ^= true; - break; case 'm': mirror ^= true; - break; case '+': scale++; - break; case '-': if (scale > 1) scale--; - break; default: if (in >= '0' && in <= '9') setBit(in); - } - return true; + size_t pixel = (BITS_TOTAL + 7) / 8; + size_t row = width * BITS_TOTAL / 8; + switch (in) { + case 'q': return false; + break; case 'x': dump = DUMP_ONE; + break; case 'X': dump ^= DUMP_ALL; + break; case 'o': formatOptions(); printf("%s\n", options); + break; case '[': if (!space--) space = COLOR__COUNT - 1; + break; case ']': if (++space == COLOR__COUNT) space = 0; + break; case 'p': palSample(); + break; case 'P': palDump(); + break; case '{': if (!preset--) preset = PRESETS_LEN - 1; setPreset(); + break; case '}': if (++preset == PRESETS_LEN) preset = 0; setPreset(); + break; case 'e': byteOrder ^= ENDIAN_BIG; + break; case 'E': bitOrder ^= ENDIAN_BIG; + break; case 'h': if (offset) offset--; + break; case 'j': offset += pixel; + break; case 'k': if (offset >= pixel) offset -= pixel; + break; case 'l': offset++; + break; case 'H': if (offset >= row) offset -= row; + break; case 'J': offset += width * row; + break; case 'K': if (offset >= width * row) offset -= width * row; + break; case 'L': offset += row; + break; case '.': width++; + break; case ',': if (width > 1) width--; + break; case '>': width *= 2; + break; case '<': if (width > 1) width /= 2; + break; case 'f': flip ^= true; + break; case 'm': mirror ^= true; + break; case '+': scale++; + break; case '-': if (scale > 1) scale--; + break; default: if (in >= '0' && in <= '9') setBit(in); + } + return true; } diff --git a/bin/glitch.c b/bin/glitch.c index 5280d7e2..6732522d 100644 --- a/bin/glitch.c +++ b/bin/glitch.c @@ -35,455 +35,455 @@ static FILE *file; static uint32_t crc; static void readExpect(void *ptr, size_t size, const char *expect) { - fread(ptr, size, 1, file); - if (ferror(file)) err(EX_IOERR, "%s", path); - if (feof(file)) errx(EX_DATAERR, "%s: missing %s", path, expect); - crc = crc32(crc, ptr, size); + fread(ptr, size, 1, file); + if (ferror(file)) err(EX_IOERR, "%s", path); + if (feof(file)) errx(EX_DATAERR, "%s: missing %s", path, expect); + crc = crc32(crc, ptr, size); } static void writeExpect(const void *ptr, size_t size) { - fwrite(ptr, size, 1, file); - if (ferror(file)) err(EX_IOERR, "%s", path); - crc = crc32(crc, ptr, size); + fwrite(ptr, size, 1, file); + if (ferror(file)) err(EX_IOERR, "%s", path); + crc = crc32(crc, ptr, size); } static const uint8_t SIGNATURE[8] = { - 0x89, 'P', 'N', 'G', '\r', '\n', 0x1A, '\n' + 0x89, 'P', 'N', 'G', '\r', '\n', 0x1A, '\n' }; static void readSignature(void) { - uint8_t signature[8]; - readExpect(signature, 8, "signature"); - if (0 != memcmp(signature, SIGNATURE, 8)) { - errx(EX_DATAERR, "%s: invalid signature", path); - } + uint8_t signature[8]; + readExpect(signature, 8, "signature"); + if (0 != memcmp(signature, SIGNATURE, 8)) { + errx(EX_DATAERR, "%s: invalid signature", path); + } } static void writeSignature(void) { - writeExpect(SIGNATURE, sizeof(SIGNATURE)); + writeExpect(SIGNATURE, sizeof(SIGNATURE)); } struct PACKED Chunk { - uint32_t size; - char type[4]; + uint32_t size; + char type[4]; }; static const char *typeStr(struct Chunk chunk) { - static char buf[5]; - memcpy(buf, chunk.type, 4); - return buf; + static char buf[5]; + memcpy(buf, chunk.type, 4); + return buf; } static struct Chunk readChunk(void) { - struct Chunk chunk; - readExpect(&chunk, sizeof(chunk), "chunk"); - chunk.size = ntohl(chunk.size); - crc = crc32(CRC_INIT, (Byte *)chunk.type, sizeof(chunk.type)); - return chunk; + struct Chunk chunk; + readExpect(&chunk, sizeof(chunk), "chunk"); + chunk.size = ntohl(chunk.size); + crc = crc32(CRC_INIT, (Byte *)chunk.type, sizeof(chunk.type)); + return chunk; } static void writeChunk(struct Chunk chunk) { - chunk.size = htonl(chunk.size); - writeExpect(&chunk, sizeof(chunk)); - crc = crc32(CRC_INIT, (Byte *)chunk.type, sizeof(chunk.type)); + chunk.size = htonl(chunk.size); + writeExpect(&chunk, sizeof(chunk)); + crc = crc32(CRC_INIT, (Byte *)chunk.type, sizeof(chunk.type)); } static void readCrc(void) { - uint32_t expected = crc; - uint32_t found; - readExpect(&found, sizeof(found), "CRC32"); - found = ntohl(found); - if (found != expected) { - errx( - EX_DATAERR, "%s: expected CRC32 %08X, found %08X", - path, expected, found - ); - } + uint32_t expected = crc; + uint32_t found; + readExpect(&found, sizeof(found), "CRC32"); + found = ntohl(found); + if (found != expected) { + errx( + EX_DATAERR, "%s: expected CRC32 %08X, found %08X", + path, expected, found + ); + } } static void writeCrc(void) { - uint32_t net = htonl(crc); - writeExpect(&net, sizeof(net)); + uint32_t net = htonl(crc); + writeExpect(&net, sizeof(net)); } static void skipChunk(struct Chunk chunk) { - uint8_t discard[chunk.size]; - readExpect(discard, sizeof(discard), "chunk data"); - readCrc(); + uint8_t discard[chunk.size]; + readExpect(discard, sizeof(discard), "chunk data"); + readCrc(); } static struct PACKED { - uint32_t width; - uint32_t height; - uint8_t depth; - enum PACKED { - GRAYSCALE = 0, - TRUECOLOR = 2, - INDEXED = 3, - GRAYSCALE_ALPHA = 4, - TRUECOLOR_ALPHA = 6, - } color; - uint8_t compression; - uint8_t filter; - uint8_t interlace; + uint32_t width; + uint32_t height; + uint8_t depth; + enum PACKED { + GRAYSCALE = 0, + TRUECOLOR = 2, + INDEXED = 3, + GRAYSCALE_ALPHA = 4, + TRUECOLOR_ALPHA = 6, + } color; + uint8_t compression; + uint8_t filter; + uint8_t interlace; } header; static_assert(13 == sizeof(header), "header size"); static size_t lineSize(void) { - switch (header.color) { - case GRAYSCALE: return (header.width * 1 * header.depth + 7) / 8; - case TRUECOLOR: return (header.width * 3 * header.depth + 7) / 8; - case INDEXED: return (header.width * 1 * header.depth + 7) / 8; - case GRAYSCALE_ALPHA: return (header.width * 2 * header.depth + 7) / 8; - case TRUECOLOR_ALPHA: return (header.width * 4 * header.depth + 7) / 8; - default: abort(); - } + switch (header.color) { + case GRAYSCALE: return (header.width * 1 * header.depth + 7) / 8; + case TRUECOLOR: return (header.width * 3 * header.depth + 7) / 8; + case INDEXED: return (header.width * 1 * header.depth + 7) / 8; + case GRAYSCALE_ALPHA: return (header.width * 2 * header.depth + 7) / 8; + case TRUECOLOR_ALPHA: return (header.width * 4 * header.depth + 7) / 8; + default: abort(); + } } static size_t dataSize(void) { - return (1 + lineSize()) * header.height; + return (1 + lineSize()) * header.height; } static void readHeader(void) { - struct Chunk ihdr = readChunk(); - if (0 != memcmp(ihdr.type, "IHDR", 4)) { - errx(EX_DATAERR, "%s: expected IHDR, found %s", path, typeStr(ihdr)); - } - if (ihdr.size != sizeof(header)) { - errx( - EX_DATAERR, "%s: expected IHDR size %zu, found %u", - path, sizeof(header), ihdr.size - ); - } - readExpect(&header, sizeof(header), "header"); - readCrc(); - header.width = ntohl(header.width); - header.height = ntohl(header.height); - if (!header.width) errx(EX_DATAERR, "%s: invalid width 0", path); - if (!header.height) errx(EX_DATAERR, "%s: invalid height 0", path); + struct Chunk ihdr = readChunk(); + if (0 != memcmp(ihdr.type, "IHDR", 4)) { + errx(EX_DATAERR, "%s: expected IHDR, found %s", path, typeStr(ihdr)); + } + if (ihdr.size != sizeof(header)) { + errx( + EX_DATAERR, "%s: expected IHDR size %zu, found %u", + path, sizeof(header), ihdr.size + ); + } + readExpect(&header, sizeof(header), "header"); + readCrc(); + header.width = ntohl(header.width); + header.height = ntohl(header.height); + if (!header.width) errx(EX_DATAERR, "%s: invalid width 0", path); + if (!header.height) errx(EX_DATAERR, "%s: invalid height 0", path); } static void writeHeader(void) { - struct Chunk ihdr = { .size = sizeof(header), .type = "IHDR" }; - writeChunk(ihdr); - header.width = htonl(header.width); - header.height = htonl(header.height); - writeExpect(&header, sizeof(header)); - writeCrc(); - header.width = ntohl(header.width); - header.height = ntohl(header.height); + struct Chunk ihdr = { .size = sizeof(header), .type = "IHDR" }; + writeChunk(ihdr); + header.width = htonl(header.width); + header.height = htonl(header.height); + writeExpect(&header, sizeof(header)); + writeCrc(); + header.width = ntohl(header.width); + header.height = ntohl(header.height); } static struct { - uint32_t len; - uint8_t entries[256][3]; + uint32_t len; + uint8_t entries[256][3]; } palette; static void readPalette(void) { - struct Chunk chunk; - for (;;) { - chunk = readChunk(); - if (0 == memcmp(chunk.type, "PLTE", 4)) break; - skipChunk(chunk); - } - palette.len = chunk.size / 3; - readExpect(palette.entries, chunk.size, "palette data"); - readCrc(); + struct Chunk chunk; + for (;;) { + chunk = readChunk(); + if (0 == memcmp(chunk.type, "PLTE", 4)) break; + skipChunk(chunk); + } + palette.len = chunk.size / 3; + readExpect(palette.entries, chunk.size, "palette data"); + readCrc(); } static void writePalette(void) { - struct Chunk plte = { .size = 3 * palette.len, .type = "PLTE" }; - writeChunk(plte); - writeExpect(palette.entries, plte.size); - writeCrc(); + struct Chunk plte = { .size = 3 * palette.len, .type = "PLTE" }; + writeChunk(plte); + writeExpect(palette.entries, plte.size); + writeCrc(); } static uint8_t *data; static void readData(void) { - data = malloc(dataSize()); - if (!data) err(EX_OSERR, "malloc(%zu)", dataSize()); - - struct z_stream_s stream = { .next_out = data, .avail_out = dataSize() }; - int error = inflateInit(&stream); - if (error != Z_OK) errx(EX_SOFTWARE, "%s: inflateInit: %s", path, stream.msg); - - for (;;) { - struct Chunk chunk = readChunk(); - if (0 == memcmp(chunk.type, "IDAT", 4)) { - uint8_t idat[chunk.size]; - readExpect(idat, sizeof(idat), "image data"); - readCrc(); - - stream.next_in = idat; - stream.avail_in = sizeof(idat); - int error = inflate(&stream, Z_SYNC_FLUSH); - if (error == Z_STREAM_END) break; - if (error != Z_OK) errx(EX_DATAERR, "%s: inflate: %s", path, stream.msg); - - } else if (0 == memcmp(chunk.type, "IEND", 4)) { - errx(EX_DATAERR, "%s: missing IDAT chunk", path); - } else { - skipChunk(chunk); - } - } - - inflateEnd(&stream); - if (stream.total_out != dataSize()) { - errx( - EX_DATAERR, "%s: expected data size %zu, found %lu", - path, dataSize(), stream.total_out - ); - } + data = malloc(dataSize()); + if (!data) err(EX_OSERR, "malloc(%zu)", dataSize()); + + struct z_stream_s stream = { .next_out = data, .avail_out = dataSize() }; + int error = inflateInit(&stream); + if (error != Z_OK) errx(EX_SOFTWARE, "%s: inflateInit: %s", path, stream.msg); + + for (;;) { + struct Chunk chunk = readChunk(); + if (0 == memcmp(chunk.type, "IDAT", 4)) { + uint8_t idat[chunk.size]; + readExpect(idat, sizeof(idat), "image data"); + readCrc(); + + stream.next_in = idat; + stream.avail_in = sizeof(idat); + int error = inflate(&stream, Z_SYNC_FLUSH); + if (error == Z_STREAM_END) break; + if (error != Z_OK) errx(EX_DATAERR, "%s: inflate: %s", path, stream.msg); + + } else if (0 == memcmp(chunk.type, "IEND", 4)) { + errx(EX_DATAERR, "%s: missing IDAT chunk", path); + } else { + skipChunk(chunk); + } + } + + inflateEnd(&stream); + if (stream.total_out != dataSize()) { + errx( + EX_DATAERR, "%s: expected data size %zu, found %lu", + path, dataSize(), stream.total_out + ); + } } static void writeData(void) { - uLong size = compressBound(dataSize()); - uint8_t deflate[size]; - int error = compress2(deflate, &size, data, dataSize(), Z_BEST_SPEED); - if (error != Z_OK) errx(EX_SOFTWARE, "%s: compress2: %d", path, error); - - struct Chunk idat = { .size = size, .type = "IDAT" }; - writeChunk(idat); - writeExpect(deflate, size); - writeCrc(); + uLong size = compressBound(dataSize()); + uint8_t deflate[size]; + int error = compress2(deflate, &size, data, dataSize(), Z_BEST_SPEED); + if (error != Z_OK) errx(EX_SOFTWARE, "%s: compress2: %d", path, error); + + struct Chunk idat = { .size = size, .type = "IDAT" }; + writeChunk(idat); + writeExpect(deflate, size); + writeCrc(); } static void writeEnd(void) { - struct Chunk iend = { .size = 0, .type = "IEND" }; - writeChunk(iend); - writeCrc(); + struct Chunk iend = { .size = 0, .type = "IEND" }; + writeChunk(iend); + writeCrc(); } enum PACKED Filter { - NONE, - SUB, - UP, - AVERAGE, - PAETH, - FILTER_COUNT, + NONE, + SUB, + UP, + AVERAGE, + PAETH, + FILTER_COUNT, }; static struct { - bool brokenPaeth; - bool filt; - bool recon; - uint8_t declareFilter; - uint8_t applyFilter; - enum Filter declareFilters[255]; - enum Filter applyFilters[255]; + bool brokenPaeth; + bool filt; + bool recon; + uint8_t declareFilter; + uint8_t applyFilter; + enum Filter declareFilters[255]; + enum Filter applyFilters[255]; } options; struct Bytes { - uint8_t x; - uint8_t a; - uint8_t b; - uint8_t c; + uint8_t x; + uint8_t a; + uint8_t b; + uint8_t c; }; static uint8_t paethPredictor(struct Bytes f) { - int32_t p = (int32_t)f.a + (int32_t)f.b - (int32_t)f.c; - int32_t pa = abs(p - (int32_t)f.a); - int32_t pb = abs(p - (int32_t)f.b); - int32_t pc = abs(p - (int32_t)f.c); - if (pa <= pb && pa <= pc) return f.a; - if (options.brokenPaeth) { - if (pb < pc) return f.b; - } else { - if (pb <= pc) return f.b; - } - return f.c; + int32_t p = (int32_t)f.a + (int32_t)f.b - (int32_t)f.c; + int32_t pa = abs(p - (int32_t)f.a); + int32_t pb = abs(p - (int32_t)f.b); + int32_t pc = abs(p - (int32_t)f.c); + if (pa <= pb && pa <= pc) return f.a; + if (options.brokenPaeth) { + if (pb < pc) return f.b; + } else { + if (pb <= pc) return f.b; + } + return f.c; } static uint8_t recon(enum Filter type, struct Bytes f) { - switch (type) { - case NONE: return f.x; - case SUB: return f.x + f.a; - case UP: return f.x + f.b; - case AVERAGE: return f.x + ((uint32_t)f.a + (uint32_t)f.b) / 2; - case PAETH: return f.x + paethPredictor(f); - default: abort(); - } + switch (type) { + case NONE: return f.x; + case SUB: return f.x + f.a; + case UP: return f.x + f.b; + case AVERAGE: return f.x + ((uint32_t)f.a + (uint32_t)f.b) / 2; + case PAETH: return f.x + paethPredictor(f); + default: abort(); + } } static uint8_t filt(enum Filter type, struct Bytes f) { - switch (type) { - case NONE: return f.x; - case SUB: return f.x - f.a; - case UP: return f.x - f.b; - case AVERAGE: return f.x - ((uint32_t)f.a + (uint32_t)f.b) / 2; - case PAETH: return f.x - paethPredictor(f); - default: abort(); - } + switch (type) { + case NONE: return f.x; + case SUB: return f.x - f.a; + case UP: return f.x - f.b; + case AVERAGE: return f.x - ((uint32_t)f.a + (uint32_t)f.b) / 2; + case PAETH: return f.x - paethPredictor(f); + default: abort(); + } } static struct Line { - enum Filter type; - uint8_t data[]; + enum Filter type; + uint8_t data[]; } **lines; static void scanlines(void) { - lines = calloc(header.height, sizeof(*lines)); - if (!lines) err(EX_OSERR, "calloc(%u, %zu)", header.height, sizeof(*lines)); - - size_t stride = 1 + lineSize(); - for (uint32_t y = 0; y < header.height; ++y) { - lines[y] = (struct Line *)&data[y * stride]; - if (lines[y]->type >= FILTER_COUNT) { - errx(EX_DATAERR, "%s: invalid filter type %hhu", path, lines[y]->type); - } - } + lines = calloc(header.height, sizeof(*lines)); + if (!lines) err(EX_OSERR, "calloc(%u, %zu)", header.height, sizeof(*lines)); + + size_t stride = 1 + lineSize(); + for (uint32_t y = 0; y < header.height; ++y) { + lines[y] = (struct Line *)&data[y * stride]; + if (lines[y]->type >= FILTER_COUNT) { + errx(EX_DATAERR, "%s: invalid filter type %hhu", path, lines[y]->type); + } + } } static struct Bytes origBytes(uint32_t y, size_t i) { - size_t pixelSize = lineSize() / header.width; - if (!pixelSize) pixelSize = 1; - bool a = (i >= pixelSize), b = (y > 0), c = (a && b); - return (struct Bytes) { - .x = lines[y]->data[i], - .a = a ? lines[y]->data[i - pixelSize] : 0, - .b = b ? lines[y - 1]->data[i] : 0, - .c = c ? lines[y - 1]->data[i - pixelSize] : 0, - }; + size_t pixelSize = lineSize() / header.width; + if (!pixelSize) pixelSize = 1; + bool a = (i >= pixelSize), b = (y > 0), c = (a && b); + return (struct Bytes) { + .x = lines[y]->data[i], + .a = a ? lines[y]->data[i - pixelSize] : 0, + .b = b ? lines[y - 1]->data[i] : 0, + .c = c ? lines[y - 1]->data[i - pixelSize] : 0, + }; } static void reconData(void) { - for (uint32_t y = 0; y < header.height; ++y) { - for (size_t i = 0; i < lineSize(); ++i) { - if (options.filt) { - lines[y]->data[i] = filt(lines[y]->type, origBytes(y, i)); - } else { - lines[y]->data[i] = recon(lines[y]->type, origBytes(y, i)); - } - } - lines[y]->type = NONE; - } + for (uint32_t y = 0; y < header.height; ++y) { + for (size_t i = 0; i < lineSize(); ++i) { + if (options.filt) { + lines[y]->data[i] = filt(lines[y]->type, origBytes(y, i)); + } else { + lines[y]->data[i] = recon(lines[y]->type, origBytes(y, i)); + } + } + lines[y]->type = NONE; + } } static void filterData(void) { - for (uint32_t y = header.height - 1; y < header.height; --y) { - uint8_t filter[FILTER_COUNT][lineSize()]; - uint32_t heuristic[FILTER_COUNT] = {0}; - enum Filter minType = NONE; - for (enum Filter type = NONE; type < FILTER_COUNT; ++type) { - for (size_t i = 0; i < lineSize(); ++i) { - if (options.recon) { - filter[type][i] = recon(type, origBytes(y, i)); - } else { - filter[type][i] = filt(type, origBytes(y, i)); - } - heuristic[type] += abs((int8_t)filter[type][i]); - } - if (heuristic[type] < heuristic[minType]) minType = type; - } - - if (options.declareFilter) { - lines[y]->type = options.declareFilters[y % options.declareFilter]; - } else { - lines[y]->type = minType; - } - - if (options.applyFilter) { - enum Filter type = options.applyFilters[y % options.applyFilter]; - memcpy(lines[y]->data, filter[type], lineSize()); - } else { - memcpy(lines[y]->data, filter[minType], lineSize()); - } - } + for (uint32_t y = header.height - 1; y < header.height; --y) { + uint8_t filter[FILTER_COUNT][lineSize()]; + uint32_t heuristic[FILTER_COUNT] = {0}; + enum Filter minType = NONE; + for (enum Filter type = NONE; type < FILTER_COUNT; ++type) { + for (size_t i = 0; i < lineSize(); ++i) { + if (options.recon) { + filter[type][i] = recon(type, origBytes(y, i)); + } else { + filter[type][i] = filt(type, origBytes(y, i)); + } + heuristic[type] += abs((int8_t)filter[type][i]); + } + if (heuristic[type] < heuristic[minType]) minType = type; + } + + if (options.declareFilter) { + lines[y]->type = options.declareFilters[y % options.declareFilter]; + } else { + lines[y]->type = minType; + } + + if (options.applyFilter) { + enum Filter type = options.applyFilters[y % options.applyFilter]; + memcpy(lines[y]->data, filter[type], lineSize()); + } else { + memcpy(lines[y]->data, filter[minType], lineSize()); + } + } } static void glitch(const char *inPath, const char *outPath) { - if (inPath) { - path = inPath; - file = fopen(path, "r"); - if (!file) err(EX_NOINPUT, "%s", path); - } else { - path = "(stdin)"; - file = stdin; - } - - readSignature(); - readHeader(); - if (header.color == INDEXED) readPalette(); - readData(); - fclose(file); - - scanlines(); - reconData(); - filterData(); - free(lines); - - if (outPath) { - path = outPath; - file = fopen(path, "w"); - if (!file) err(EX_CANTCREAT, "%s", path); - } else { - path = "(stdout)"; - file = stdout; - } - - writeSignature(); - writeHeader(); - if (header.color == INDEXED) writePalette(); - writeData(); - writeEnd(); - free(data); - - int error = fclose(file); - if (error) err(EX_IOERR, "%s", path); + if (inPath) { + path = inPath; + file = fopen(path, "r"); + if (!file) err(EX_NOINPUT, "%s", path); + } else { + path = "(stdin)"; + file = stdin; + } + + readSignature(); + readHeader(); + if (header.color == INDEXED) readPalette(); + readData(); + fclose(file); + + scanlines(); + reconData(); + filterData(); + free(lines); + + if (outPath) { + path = outPath; + file = fopen(path, "w"); + if (!file) err(EX_CANTCREAT, "%s", path); + } else { + path = "(stdout)"; + file = stdout; + } + + writeSignature(); + writeHeader(); + if (header.color == INDEXED) writePalette(); + writeData(); + writeEnd(); + free(data); + + int error = fclose(file); + if (error) err(EX_IOERR, "%s", path); } static enum Filter parseFilter(const char *s) { - switch (s[0]) { - case 'N': case 'n': return NONE; - case 'S': case 's': return SUB; - case 'U': case 'u': return UP; - case 'A': case 'a': return AVERAGE; - case 'P': case 'p': return PAETH; - default: errx(EX_USAGE, "invalid filter type %s", s); - } + switch (s[0]) { + case 'N': case 'n': return NONE; + case 'S': case 's': return SUB; + case 'U': case 'u': return UP; + case 'A': case 'a': return AVERAGE; + case 'P': case 'p': return PAETH; + default: errx(EX_USAGE, "invalid filter type %s", s); + } } static uint8_t parseFilters(enum Filter *filters, const char *s) { - uint8_t len = 0; - do { - filters[len++] = parseFilter(s); - s = strchr(s, ','); - } while (s++); - return len; + uint8_t len = 0; + do { + filters[len++] = parseFilter(s); + s = strchr(s, ','); + } while (s++); + return len; } int main(int argc, char *argv[]) { - bool stdio = false; - char *output = NULL; - - int opt; - while (0 < (opt = getopt(argc, argv, "a:cd:fo:pr"))) { - switch (opt) { - case 'a': { - options.applyFilter = parseFilters(options.applyFilters, optarg); - } break; - case 'c': stdio = true; break; - case 'd': { - options.declareFilter = parseFilters(options.declareFilters, optarg); - } break; - case 'f': options.filt = true; break; - case 'o': output = optarg; break; - case 'p': options.brokenPaeth = true; break; - case 'r': options.recon = true; break; - default: return EX_USAGE; - } - } - - if (argc - optind == 1 && (output || stdio)) { - glitch(argv[optind], output); - } else if (optind < argc) { - for (int i = optind; i < argc; ++i) { - glitch(argv[i], argv[i]); - } - } else { - glitch(NULL, output); - } - - return EX_OK; + bool stdio = false; + char *output = NULL; + + int opt; + while (0 < (opt = getopt(argc, argv, "a:cd:fo:pr"))) { + switch (opt) { + case 'a': { + options.applyFilter = parseFilters(options.applyFilters, optarg); + } break; + case 'c': stdio = true; break; + case 'd': { + options.declareFilter = parseFilters(options.declareFilters, optarg); + } break; + case 'f': options.filt = true; break; + case 'o': output = optarg; break; + case 'p': options.brokenPaeth = true; break; + case 'r': options.recon = true; break; + default: return EX_USAGE; + } + } + + if (argc - optind == 1 && (output || stdio)) { + glitch(argv[optind], output); + } else if (optind < argc) { + for (int i = optind; i < argc; ++i) { + glitch(argv[i], argv[i]); + } + } else { + glitch(NULL, output); + } + + return EX_OK; } diff --git a/bin/hnel.c b/bin/hnel.c index 82f990d4..20dbd2a7 100644 --- a/bin/hnel.c +++ b/bin/hnel.c @@ -35,84 +35,84 @@ static struct termios saveTerm; static void restoreTerm(void) { - tcsetattr(STDIN_FILENO, TCSADRAIN, &saveTerm); + tcsetattr(STDIN_FILENO, TCSADRAIN, &saveTerm); } int main(int argc, char *argv[]) { - int error; - - if (argc < 4) return EX_USAGE; - - char table[256] = {0}; - if (strlen(argv[1]) != strlen(argv[2])) return EX_USAGE; - for (const char *from = argv[1], *to = argv[2]; *from; ++from, ++to) { - table[(unsigned)*from] = *to; - } - - error = tcgetattr(STDERR_FILENO, &saveTerm); - if (error) err(EX_IOERR, "tcgetattr"); - atexit(restoreTerm); - - struct termios raw; - cfmakeraw(&raw); - error = tcsetattr(STDERR_FILENO, TCSADRAIN, &raw); - if (error) err(EX_IOERR, "tcsetattr"); - - struct winsize window; - error = ioctl(STDERR_FILENO, TIOCGWINSZ, &window); - if (error) err(EX_IOERR, "TIOCGWINSZ"); - - int pty; - pid_t pid = forkpty(&pty, NULL, NULL, &window); - if (pid < 0) err(EX_OSERR, "forkpty"); - - if (!pid) { - execvp(argv[3], &argv[3]); - err(EX_NOINPUT, "%s", argv[3]); - } - - bool enable = true; - - char buf[4096]; - struct pollfd fds[2] = { - { .fd = STDIN_FILENO, .events = POLLIN }, - { .fd = pty, .events = POLLIN }, - }; - while (0 < poll(fds, 2, -1)) { - if (fds[0].revents & POLLIN) { - ssize_t readSize = read(STDIN_FILENO, buf, sizeof(buf)); - if (readSize < 0) err(EX_IOERR, "read(%d)", STDIN_FILENO); - - if (readSize == 1) { - if (buf[0] == CTRL('S')) { - enable ^= true; - continue; - } - - unsigned char c = buf[0]; - if (enable && table[c]) buf[0] = table[c]; - } - - ssize_t writeSize = write(pty, buf, readSize); - if (writeSize < 0) err(EX_IOERR, "write(%d)", pty); - if (writeSize < readSize) errx(EX_IOERR, "short write(%d)", pty); - } - - if (fds[1].revents & POLLIN) { - ssize_t readSize = read(pty, buf, sizeof(buf)); - if (readSize < 0) err(EX_IOERR, "read(%d)", pty); - - ssize_t writeSize = write(STDOUT_FILENO, buf, readSize); - if (writeSize < 0) err(EX_IOERR, "write(%d)", STDOUT_FILENO); - if (writeSize < readSize) { - errx(EX_IOERR, "short write(%d)", STDOUT_FILENO); - } - } - - int status; - pid_t dead = waitpid(pid, &status, WNOHANG); - if (dead < 0) err(EX_OSERR, "waitpid(%d)", pid); - if (dead) return WIFEXITED(status) ? WEXITSTATUS(status) : EX_SOFTWARE; - } - err(EX_IOERR, "poll"); + int error; + + if (argc < 4) return EX_USAGE; + + char table[256] = {0}; + if (strlen(argv[1]) != strlen(argv[2])) return EX_USAGE; + for (const char *from = argv[1], *to = argv[2]; *from; ++from, ++to) { + table[(unsigned)*from] = *to; + } + + error = tcgetattr(STDERR_FILENO, &saveTerm); + if (error) err(EX_IOERR, "tcgetattr"); + atexit(restoreTerm); + + struct termios raw; + cfmakeraw(&raw); + error = tcsetattr(STDERR_FILENO, TCSADRAIN, &raw); + if (error) err(EX_IOERR, "tcsetattr"); + + struct winsize window; + error = ioctl(STDERR_FILENO, TIOCGWINSZ, &window); + if (error) err(EX_IOERR, "TIOCGWINSZ"); + + int pty; + pid_t pid = forkpty(&pty, NULL, NULL, &window); + if (pid < 0) err(EX_OSERR, "forkpty"); + + if (!pid) { + execvp(argv[3], &argv[3]); + err(EX_NOINPUT, "%s", argv[3]); + } + + bool enable = true; + + char buf[4096]; + struct pollfd fds[2] = { + { .fd = STDIN_FILENO, .events = POLLIN }, + { .fd = pty, .events = POLLIN }, + }; + while (0 < poll(fds, 2, -1)) { + if (fds[0].revents & POLLIN) { + ssize_t readSize = read(STDIN_FILENO, buf, sizeof(buf)); + if (readSize < 0) err(EX_IOERR, "read(%d)", STDIN_FILENO); + + if (readSize == 1) { + if (buf[0] == CTRL('S')) { + enable ^= true; + continue; + } + + unsigned char c = buf[0]; + if (enable && table[c]) buf[0] = table[c]; + } + + ssize_t writeSize = write(pty, buf, readSize); + if (writeSize < 0) err(EX_IOERR, "write(%d)", pty); + if (writeSize < readSize) errx(EX_IOERR, "short write(%d)", pty); + } + + if (fds[1].revents & POLLIN) { + ssize_t readSize = read(pty, buf, sizeof(buf)); + if (readSize < 0) err(EX_IOERR, "read(%d)", pty); + + ssize_t writeSize = write(STDOUT_FILENO, buf, readSize); + if (writeSize < 0) err(EX_IOERR, "write(%d)", STDOUT_FILENO); + if (writeSize < readSize) { + errx(EX_IOERR, "short write(%d)", STDOUT_FILENO); + } + } + + int status; + pid_t dead = waitpid(pid, &status, WNOHANG); + if (dead < 0) err(EX_OSERR, "waitpid(%d)", pid); + if (dead) return WIFEXITED(status) ? WEXITSTATUS(status) : EX_SOFTWARE; + } + err(EX_IOERR, "poll"); } diff --git a/bin/klon.c b/bin/klon.c index 05adc278..2a5e1346 100644 --- a/bin/klon.c +++ b/bin/klon.c @@ -26,334 +26,334 @@ typedef uint8_t Card; enum { - MASK_RANK = 0x0F, - MASK_SUIT = 0x30, - MASK_COLOR = 0x10, - MASK_UP = 0x40, - MASK_SELECT = 0x80, + MASK_RANK = 0x0F, + MASK_SUIT = 0x30, + MASK_COLOR = 0x10, + MASK_UP = 0x40, + MASK_SELECT = 0x80, }; enum { - SUIT_CLUB = 0x00, - SUIT_DIAMOND = 0x10, - SUIT_SPADE = 0x20, - SUIT_HEART = 0x30, + SUIT_CLUB = 0x00, + SUIT_DIAMOND = 0x10, + SUIT_SPADE = 0x20, + SUIT_HEART = 0x30, }; struct Stack { - Card data[52]; - uint8_t index; + Card data[52]; + uint8_t index; }; #define EMPTY { .data = {0}, .index = 52 } static void push(struct Stack *stack, Card card) { - assert(stack->index > 0); - stack->data[--stack->index] = card; + assert(stack->index > 0); + stack->data[--stack->index] = card; } static Card pop(struct Stack *stack) { - assert(stack->index < 52); - return stack->data[stack->index++]; + assert(stack->index < 52); + return stack->data[stack->index++]; } static Card get(const struct Stack *stack, uint8_t i) { - if (stack->index + i > 51) return 0; - return stack->data[stack->index + i]; + if (stack->index + i > 51) return 0; + return stack->data[stack->index + i]; } static uint8_t len(const struct Stack *stack) { - return 52 - stack->index; + return 52 - stack->index; } struct State { - struct Stack stock; - struct Stack waste; - struct Stack found[4]; - struct Stack table[7]; + struct Stack stock; + struct Stack waste; + struct Stack found[4]; + struct Stack table[7]; }; static struct State g = { - .stock = { - .data = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, - 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, - }, - .index = 0, - }, - .waste = EMPTY, - .found = { EMPTY, EMPTY, EMPTY, EMPTY }, - .table = { - EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY - }, + .stock = { + .data = { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, + }, + .index = 0, + }, + .waste = EMPTY, + .found = { EMPTY, EMPTY, EMPTY, EMPTY }, + .table = { + EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY + }, }; static struct State save; static void checkpoint(void) { - memcpy(&save, &g, sizeof(struct State)); + memcpy(&save, &g, sizeof(struct State)); } static void undo(void) { - memcpy(&g, &save, sizeof(struct State)); + memcpy(&g, &save, sizeof(struct State)); } static void shuffle(void) { - for (int i = 51; i > 0; --i) { - int j = arc4random_uniform(i + 1); - uint8_t x = g.stock.data[i]; - g.stock.data[i] = g.stock.data[j]; - g.stock.data[j] = x; - } + for (int i = 51; i > 0; --i) { + int j = arc4random_uniform(i + 1); + uint8_t x = g.stock.data[i]; + g.stock.data[i] = g.stock.data[j]; + g.stock.data[j] = x; + } } static void deal(void) { - for (int i = 0; i < 7; ++i) { - for (int j = i; j < 7; ++j) { - push(&g.table[j], pop(&g.stock)); - } - } + for (int i = 0; i < 7; ++i) { + for (int j = i; j < 7; ++j) { + push(&g.table[j], pop(&g.stock)); + } + } } static void reveal(void) { - for (int i = 0; i < 7; ++i) { - if (get(&g.table[i], 0)) { - push(&g.table[i], pop(&g.table[i]) | MASK_UP); - } - } + for (int i = 0; i < 7; ++i) { + if (get(&g.table[i], 0)) { + push(&g.table[i], pop(&g.table[i]) | MASK_UP); + } + } } static void draw(void) { - if (get(&g.stock, 0)) push(&g.waste, pop(&g.stock) | MASK_UP); - if (get(&g.stock, 0)) push(&g.waste, pop(&g.stock) | MASK_UP); - if (get(&g.stock, 0)) push(&g.waste, pop(&g.stock) | MASK_UP); + if (get(&g.stock, 0)) push(&g.waste, pop(&g.stock) | MASK_UP); + if (get(&g.stock, 0)) push(&g.waste, pop(&g.stock) | MASK_UP); + if (get(&g.stock, 0)) push(&g.waste, pop(&g.stock) | MASK_UP); } static void wasted(void) { - uint8_t n = len(&g.waste); - for (int i = 0; i < n; ++i) { - push(&g.stock, pop(&g.waste) & ~MASK_UP); - } + uint8_t n = len(&g.waste); + for (int i = 0; i < n; ++i) { + push(&g.stock, pop(&g.waste) & ~MASK_UP); + } } static void transfer(struct Stack *dest, struct Stack *src, uint8_t n) { - struct Stack temp = EMPTY; - for (int i = 0; i < n; ++i) { - push(&temp, pop(src)); - } - for (int i = 0; i < n; ++i) { - push(dest, pop(&temp)); - } + struct Stack temp = EMPTY; + for (int i = 0; i < n; ++i) { + push(&temp, pop(src)); + } + for (int i = 0; i < n; ++i) { + push(dest, pop(&temp)); + } } static bool canFound(const struct Stack *found, Card card) { - if (!get(found, 0)) return (card & MASK_RANK) == 1; - if ((card & MASK_SUIT) != (get(found, 0) & MASK_SUIT)) return false; - return (card & MASK_RANK) == (get(found, 0) & MASK_RANK) + 1; + if (!get(found, 0)) return (card & MASK_RANK) == 1; + if ((card & MASK_SUIT) != (get(found, 0) & MASK_SUIT)) return false; + return (card & MASK_RANK) == (get(found, 0) & MASK_RANK) + 1; } static bool canTable(const struct Stack *table, Card card) { - if (!get(table, 0)) return (card & MASK_RANK) == 13; - if ((card & MASK_COLOR) == (get(table, 0) & MASK_COLOR)) return false; - return (card & MASK_RANK) == (get(table, 0) & MASK_RANK) - 1; + if (!get(table, 0)) return (card & MASK_RANK) == 13; + if ((card & MASK_COLOR) == (get(table, 0) & MASK_COLOR)) return false; + return (card & MASK_RANK) == (get(table, 0) & MASK_RANK) - 1; } enum { - PAIR_EMPTY = 1, - PAIR_BACK, - PAIR_BLACK, - PAIR_RED, + PAIR_EMPTY = 1, + PAIR_BACK, + PAIR_BLACK, + PAIR_RED, }; static void curse(void) { - setlocale(LC_CTYPE, ""); - - initscr(); - cbreak(); - noecho(); - keypad(stdscr, true); - set_escdelay(100); - curs_set(0); - - start_color(); - assume_default_colors(-1, -1); - init_pair(PAIR_EMPTY, COLOR_WHITE, COLOR_BLACK); - init_pair(PAIR_BACK, COLOR_WHITE, COLOR_BLUE); - init_pair(PAIR_BLACK, COLOR_BLACK, COLOR_WHITE); - init_pair(PAIR_RED, COLOR_RED, COLOR_WHITE); + setlocale(LC_CTYPE, ""); + + initscr(); + cbreak(); + noecho(); + keypad(stdscr, true); + set_escdelay(100); + curs_set(0); + + start_color(); + assume_default_colors(-1, -1); + init_pair(PAIR_EMPTY, COLOR_WHITE, COLOR_BLACK); + init_pair(PAIR_BACK, COLOR_WHITE, COLOR_BLUE); + init_pair(PAIR_BLACK, COLOR_BLACK, COLOR_WHITE); + init_pair(PAIR_RED, COLOR_RED, COLOR_WHITE); } static const char rank[] = "\0A23456789TJQK"; static const char *suit[] = { - [SUIT_HEART] = "♥", - [SUIT_CLUB] = "♣", - [SUIT_DIAMOND] = "♦", - [SUIT_SPADE] = "♠", + [SUIT_HEART] = "♥", + [SUIT_CLUB] = "♣", + [SUIT_DIAMOND] = "♦", + [SUIT_SPADE] = "♠", }; static void renderCard(int y, int x, Card card) { - if (card & MASK_UP) { - bkgdset( - COLOR_PAIR(card & MASK_COLOR ? PAIR_RED : PAIR_BLACK) - | (card & MASK_SELECT ? A_REVERSE : A_NORMAL) - ); - - move(y, x); - addch(rank[card & MASK_RANK]); - addstr(suit[card & MASK_SUIT]); - addch(' '); - - move(y + 1, x); - addstr(suit[card & MASK_SUIT]); - addch(' '); - addstr(suit[card & MASK_SUIT]); - - move(y + 2, x); - addch(' '); - addstr(suit[card & MASK_SUIT]); - addch(rank[card & MASK_RANK]); - - } else { - bkgdset(COLOR_PAIR(card ? PAIR_BACK : PAIR_EMPTY)); - mvaddstr(y, x, " "); - mvaddstr(y + 1, x, " "); - mvaddstr(y + 2, x, " "); - } + if (card & MASK_UP) { + bkgdset( + COLOR_PAIR(card & MASK_COLOR ? PAIR_RED : PAIR_BLACK) + | (card & MASK_SELECT ? A_REVERSE : A_NORMAL) + ); + + move(y, x); + addch(rank[card & MASK_RANK]); + addstr(suit[card & MASK_SUIT]); + addch(' '); + + move(y + 1, x); + addstr(suit[card & MASK_SUIT]); + addch(' '); + addstr(suit[card & MASK_SUIT]); + + move(y + 2, x); + addch(' '); + addstr(suit[card & MASK_SUIT]); + addch(rank[card & MASK_RANK]); + + } else { + bkgdset(COLOR_PAIR(card ? PAIR_BACK : PAIR_EMPTY)); + mvaddstr(y, x, " "); + mvaddstr(y + 1, x, " "); + mvaddstr(y + 2, x, " "); + } } static void render(void) { - bkgdset(COLOR_PAIR(0)); - erase(); - - int x = 2; - int y = 1; - - renderCard(y, x, get(&g.stock, 0)); - - x += 5; - renderCard(y, x++, get(&g.waste, 2)); - renderCard(y, x++, get(&g.waste, 1)); - renderCard(y, x, get(&g.waste, 0)); - - x += 5; - for (int i = 0; i < 4; ++i) { - renderCard(y, x, get(&g.found[i], 0)); - x += 4; - } - - x = 2; - for (int i = 0; i < 7; ++i) { - y = 5; - renderCard(y, x, 0); - for (int j = len(&g.table[i]); j > 0; --j) { - renderCard(y, x, get(&g.table[i], j - 1)); - y++; - } - x += 4; - } + bkgdset(COLOR_PAIR(0)); + erase(); + + int x = 2; + int y = 1; + + renderCard(y, x, get(&g.stock, 0)); + + x += 5; + renderCard(y, x++, get(&g.waste, 2)); + renderCard(y, x++, get(&g.waste, 1)); + renderCard(y, x, get(&g.waste, 0)); + + x += 5; + for (int i = 0; i < 4; ++i) { + renderCard(y, x, get(&g.found[i], 0)); + x += 4; + } + + x = 2; + for (int i = 0; i < 7; ++i) { + y = 5; + renderCard(y, x, 0); + for (int j = len(&g.table[i]); j > 0; --j) { + renderCard(y, x, get(&g.table[i], j - 1)); + y++; + } + x += 4; + } } static struct { - struct Stack *stack; - uint8_t depth; + struct Stack *stack; + uint8_t depth; } input; static void deepen(void) { - assert(input.stack); - if (input.depth == len(input.stack)) return; - if (!(get(input.stack, input.depth) & MASK_UP)) return; - input.stack->data[input.stack->index + input.depth] |= MASK_SELECT; - input.depth++; + assert(input.stack); + if (input.depth == len(input.stack)) return; + if (!(get(input.stack, input.depth) & MASK_UP)) return; + input.stack->data[input.stack->index + input.depth] |= MASK_SELECT; + input.depth++; } static void select(struct Stack *stack) { - if (!get(stack, 0)) return; - input.stack = stack; - input.depth = 0; - deepen(); + if (!get(stack, 0)) return; + input.stack = stack; + input.depth = 0; + deepen(); } static void commit(struct Stack *dest) { - assert(input.stack); - for (int i = 0; i < input.depth; ++i) { - input.stack->data[input.stack->index + i] &= ~MASK_SELECT; - } - if (dest) { - checkpoint(); - transfer(dest, input.stack, input.depth); - } - input.stack = NULL; - input.depth = 0; + assert(input.stack); + for (int i = 0; i < input.depth; ++i) { + input.stack->data[input.stack->index + i] &= ~MASK_SELECT; + } + if (dest) { + checkpoint(); + transfer(dest, input.stack, input.depth); + } + input.stack = NULL; + input.depth = 0; } int main() { - curse(); - - shuffle(); - deal(); - checkpoint(); - - for (;;) { - reveal(); - render(); - - int c = getch(); - if (!input.stack) { - if (c == 'q') { - break; - } else if (c == 'u') { - undo(); - } else if (c == 's' || c == ' ') { - if (get(&g.stock, 0)) { - checkpoint(); - draw(); - } else { - wasted(); - } - } else if (c == 'w') { - select(&g.waste); - } else if (c >= 'a' && c <= 'd') { - select(&g.found[c - 'a']); - } else if (c >= '1' && c <= '7') { - select(&g.table[c - '1']); - } - - } else { - if (c >= '1' && c <= '7') { - struct Stack *table = &g.table[c - '1']; - if (input.stack == table) { - deepen(); - } else if (canTable(table, get(input.stack, input.depth - 1))) { - commit(table); - } else { - commit(NULL); - } - } else if (input.depth == 1 && c >= 'a' && c <= 'd') { - struct Stack *found = &g.found[c - 'a']; - if (canFound(found, get(input.stack, 0))) { - commit(found); - } else { - commit(NULL); - } - } else if (input.depth == 1 && (c == 'f' || c == '\n')) { - struct Stack *found; - for (int i = 0; i < 4; ++i) { - found = &g.found[i]; - if (canFound(found, get(input.stack, 0))) break; - found = NULL; - } - commit(found); - } else { - commit(NULL); - } - } - } - - endwin(); - return 0; + curse(); + + shuffle(); + deal(); + checkpoint(); + + for (;;) { + reveal(); + render(); + + int c = getch(); + if (!input.stack) { + if (c == 'q') { + break; + } else if (c == 'u') { + undo(); + } else if (c == 's' || c == ' ') { + if (get(&g.stock, 0)) { + checkpoint(); + draw(); + } else { + wasted(); + } + } else if (c == 'w') { + select(&g.waste); + } else if (c >= 'a' && c <= 'd') { + select(&g.found[c - 'a']); + } else if (c >= '1' && c <= '7') { + select(&g.table[c - '1']); + } + + } else { + if (c >= '1' && c <= '7') { + struct Stack *table = &g.table[c - '1']; + if (input.stack == table) { + deepen(); + } else if (canTable(table, get(input.stack, input.depth - 1))) { + commit(table); + } else { + commit(NULL); + } + } else if (input.depth == 1 && c >= 'a' && c <= 'd') { + struct Stack *found = &g.found[c - 'a']; + if (canFound(found, get(input.stack, 0))) { + commit(found); + } else { + commit(NULL); + } + } else if (input.depth == 1 && (c == 'f' || c == '\n')) { + struct Stack *found; + for (int i = 0; i < 4; ++i) { + found = &g.found[i]; + if (canFound(found, get(input.stack, 0))) break; + found = NULL; + } + commit(found); + } else { + commit(NULL); + } + } + } + + endwin(); + return 0; } diff --git a/bin/pbd.c b/bin/pbd.c index afe2a77e..77832433 100644 --- a/bin/pbd.c +++ b/bin/pbd.c @@ -29,108 +29,108 @@ #define UNUSED __attribute__((unused)) static void spawn(const char *cmd, int dest, int src) { - pid_t pid = fork(); - if (pid < 0) err(EX_OSERR, "fork"); - - if (pid) { - int status; - pid_t dead = waitpid(pid, &status, 0); - if (dead < 0) err(EX_OSERR, "waitpid(%d)", pid); - if (status) warnx("%s: status %d", cmd, status); - - } else { - int fd = dup2(src, dest); - if (fd < 0) err(EX_OSERR, "dup2"); - - execlp(cmd, cmd, NULL); - err(EX_UNAVAILABLE, "%s", cmd); - } + pid_t pid = fork(); + if (pid < 0) err(EX_OSERR, "fork"); + + if (pid) { + int status; + pid_t dead = waitpid(pid, &status, 0); + if (dead < 0) err(EX_OSERR, "waitpid(%d)", pid); + if (status) warnx("%s: status %d", cmd, status); + + } else { + int fd = dup2(src, dest); + if (fd < 0) err(EX_OSERR, "dup2"); + + execlp(cmd, cmd, NULL); + err(EX_UNAVAILABLE, "%s", cmd); + } } static int pbd(void) { - int error; + int error; - int server = socket(PF_INET, SOCK_STREAM, 0); - if (server < 0) err(EX_OSERR, "socket"); + int server = socket(PF_INET, SOCK_STREAM, 0); + if (server < 0) err(EX_OSERR, "socket"); - error = fcntl(server, F_SETFD, FD_CLOEXEC); - if (error) err(EX_IOERR, "fcntl"); + error = fcntl(server, F_SETFD, FD_CLOEXEC); + if (error) err(EX_IOERR, "fcntl"); - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_port = htons(7062), - .sin_addr = { .s_addr = htonl(0x7F000001) }, - }; - error = bind(server, (struct sockaddr *)&addr, sizeof(addr)); - if (error) err(EX_UNAVAILABLE, "bind"); + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = htons(7062), + .sin_addr = { .s_addr = htonl(0x7F000001) }, + }; + error = bind(server, (struct sockaddr *)&addr, sizeof(addr)); + if (error) err(EX_UNAVAILABLE, "bind"); - error = listen(server, 0); - if (error) err(EX_UNAVAILABLE, "listen"); + error = listen(server, 0); + if (error) err(EX_UNAVAILABLE, "listen"); - for (;;) { - int client = accept(server, NULL, NULL); - if (client < 0) err(EX_IOERR, "accept"); + for (;;) { + int client = accept(server, NULL, NULL); + if (client < 0) err(EX_IOERR, "accept"); - error = fcntl(client, F_SETFD, FD_CLOEXEC); - if (error) err(EX_IOERR, "fcntl"); + error = fcntl(client, F_SETFD, FD_CLOEXEC); + if (error) err(EX_IOERR, "fcntl"); - spawn("pbpaste", STDOUT_FILENO, client); + spawn("pbpaste", STDOUT_FILENO, client); - char p; - ssize_t peek = recv(client, &p, 1, MSG_PEEK); - if (peek < 0) err(EX_IOERR, "recv"); + char p; + ssize_t peek = recv(client, &p, 1, MSG_PEEK); + if (peek < 0) err(EX_IOERR, "recv"); - if (peek) spawn("pbcopy", STDIN_FILENO, client); + if (peek) spawn("pbcopy", STDIN_FILENO, client); - close(client); - } + close(client); + } } static int pbdClient(void) { - int client = socket(PF_INET, SOCK_STREAM, 0); - if (client < 0) err(EX_OSERR, "socket"); - - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_port = htons(7062), - .sin_addr = { .s_addr = htonl(0x7F000001) }, - }; - int error = connect(client, (struct sockaddr *)&addr, sizeof(addr)); - if (error) err(EX_UNAVAILABLE, "connect"); - - return client; + int client = socket(PF_INET, SOCK_STREAM, 0); + if (client < 0) err(EX_OSERR, "socket"); + + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = htons(7062), + .sin_addr = { .s_addr = htonl(0x7F000001) }, + }; + int error = connect(client, (struct sockaddr *)&addr, sizeof(addr)); + if (error) err(EX_UNAVAILABLE, "connect"); + + return client; } static void copy(int out, int in) { - char buf[4096]; - ssize_t readSize; - while (0 < (readSize = read(in, buf, sizeof(buf)))) { - ssize_t writeSize = write(out, buf, readSize); - if (writeSize < 0) err(EX_IOERR, "write(%d)", out); - if (writeSize < readSize) errx(EX_IOERR, "short write(%d)", out); - } - if (readSize < 0) err(EX_IOERR, "read(%d)", in); + char buf[4096]; + ssize_t readSize; + while (0 < (readSize = read(in, buf, sizeof(buf)))) { + ssize_t writeSize = write(out, buf, readSize); + if (writeSize < 0) err(EX_IOERR, "write(%d)", out); + if (writeSize < readSize) errx(EX_IOERR, "short write(%d)", out); + } + if (readSize < 0) err(EX_IOERR, "read(%d)", in); } static int pbcopy(void) { - int client = pbdClient(); - copy(client, STDIN_FILENO); - return EX_OK; + int client = pbdClient(); + copy(client, STDIN_FILENO); + return EX_OK; } static int pbpaste(void) { - int client = pbdClient(); - shutdown(client, SHUT_WR); - copy(STDOUT_FILENO, client); - return EX_OK; + int client = pbdClient(); + shutdown(client, SHUT_WR); + copy(STDOUT_FILENO, client); + return EX_OK; } int main(int argc UNUSED, char *argv[]) { - if (!argv[0][0] || !argv[0][1]) return EX_USAGE; - switch (argv[0][2]) { - case 'd': return pbd(); - case 'c': return pbcopy(); - case 'p': return pbpaste(); - default: return EX_USAGE; - } + if (!argv[0][0] || !argv[0][1]) return EX_USAGE; + switch (argv[0][2]) { + case 'd': return pbd(); + case 'c': return pbcopy(); + case 'p': return pbpaste(); + default: return EX_USAGE; + } } diff --git a/bin/pngo.c b/bin/pngo.c index 22837d76..e4afa082 100644 --- a/bin/pngo.c +++ b/bin/pngo.c @@ -37,682 +37,682 @@ static FILE *file; static uint32_t crc; static void readExpect(void *ptr, size_t size, const char *expect) { - fread(ptr, size, 1, file); - if (ferror(file)) err(EX_IOERR, "%s", path); - if (feof(file)) errx(EX_DATAERR, "%s: missing %s", path, expect); - crc = crc32(crc, ptr, size); + fread(ptr, size, 1, file); + if (ferror(file)) err(EX_IOERR, "%s", path); + if (feof(file)) errx(EX_DATAERR, "%s: missing %s", path, expect); + crc = crc32(crc, ptr, size); } static void writeExpect(const void *ptr, size_t size) { - fwrite(ptr, size, 1, file); - if (ferror(file)) err(EX_IOERR, "%s", path); - crc = crc32(crc, ptr, size); + fwrite(ptr, size, 1, file); + if (ferror(file)) err(EX_IOERR, "%s", path); + crc = crc32(crc, ptr, size); } static const uint8_t SIGNATURE[8] = { - 0x89, 'P', 'N', 'G', '\r', '\n', 0x1A, '\n' + 0x89, 'P', 'N', 'G', '\r', '\n', 0x1A, '\n' }; static void readSignature(void) { - uint8_t signature[8]; - readExpect(signature, 8, "signature"); - if (0 != memcmp(signature, SIGNATURE, 8)) { - errx(EX_DATAERR, "%s: invalid signature", path); - } + uint8_t signature[8]; + readExpect(signature, 8, "signature"); + if (0 != memcmp(signature, SIGNATURE, 8)) { + errx(EX_DATAERR, "%s: invalid signature", path); + } } static void writeSignature(void) { - writeExpect(SIGNATURE, sizeof(SIGNATURE)); + writeExpect(SIGNATURE, sizeof(SIGNATURE)); } struct PACKED Chunk { - uint32_t size; - char type[4]; + uint32_t size; + char type[4]; }; static const char *typeStr(struct Chunk chunk) { - static char buf[5]; - memcpy(buf, chunk.type, 4); - return buf; + static char buf[5]; + memcpy(buf, chunk.type, 4); + return buf; } static struct Chunk readChunk(void) { - struct Chunk chunk; - readExpect(&chunk, sizeof(chunk), "chunk"); - chunk.size = ntohl(chunk.size); - crc = crc32(CRC_INIT, (Byte *)chunk.type, sizeof(chunk.type)); - return chunk; + struct Chunk chunk; + readExpect(&chunk, sizeof(chunk), "chunk"); + chunk.size = ntohl(chunk.size); + crc = crc32(CRC_INIT, (Byte *)chunk.type, sizeof(chunk.type)); + return chunk; } static void writeChunk(struct Chunk chunk) { - chunk.size = htonl(chunk.size); - writeExpect(&chunk, sizeof(chunk)); - crc = crc32(CRC_INIT, (Byte *)chunk.type, sizeof(chunk.type)); + chunk.size = htonl(chunk.size); + writeExpect(&chunk, sizeof(chunk)); + crc = crc32(CRC_INIT, (Byte *)chunk.type, sizeof(chunk.type)); } static void readCrc(void) { - uint32_t expected = crc; - uint32_t found; - readExpect(&found, sizeof(found), "CRC32"); - found = ntohl(found); - if (found != expected) { - errx( - EX_DATAERR, "%s: expected CRC32 %08X, found %08X", - path, expected, found - ); - } + uint32_t expected = crc; + uint32_t found; + readExpect(&found, sizeof(found), "CRC32"); + found = ntohl(found); + if (found != expected) { + errx( + EX_DATAERR, "%s: expected CRC32 %08X, found %08X", + path, expected, found + ); + } } static void writeCrc(void) { - uint32_t net = htonl(crc); - writeExpect(&net, sizeof(net)); + uint32_t net = htonl(crc); + writeExpect(&net, sizeof(net)); } static void skipChunk(struct Chunk chunk) { - if (!(chunk.type[0] & 0x20)) { - errx(EX_CONFIG, "%s: unsupported critical chunk %s", path, typeStr(chunk)); - } - uint8_t discard[chunk.size]; - readExpect(discard, sizeof(discard), "chunk data"); - readCrc(); + if (!(chunk.type[0] & 0x20)) { + errx(EX_CONFIG, "%s: unsupported critical chunk %s", path, typeStr(chunk)); + } + uint8_t discard[chunk.size]; + readExpect(discard, sizeof(discard), "chunk data"); + readCrc(); } static struct PACKED { - uint32_t width; - uint32_t height; - uint8_t depth; - enum PACKED { - GRAYSCALE = 0, - TRUECOLOR = 2, - INDEXED = 3, - GRAYSCALE_ALPHA = 4, - TRUECOLOR_ALPHA = 6, - } color; - enum PACKED { DEFLATE } compression; - enum PACKED { ADAPTIVE } filter; - enum PACKED { PROGRESSIVE, ADAM7 } interlace; + uint32_t width; + uint32_t height; + uint8_t depth; + enum PACKED { + GRAYSCALE = 0, + TRUECOLOR = 2, + INDEXED = 3, + GRAYSCALE_ALPHA = 4, + TRUECOLOR_ALPHA = 6, + } color; + enum PACKED { DEFLATE } compression; + enum PACKED { ADAPTIVE } filter; + enum PACKED { PROGRESSIVE, ADAM7 } interlace; } header; static_assert(13 == sizeof(header), "header size"); static size_t lineSize(void) { - switch (header.color) { - case GRAYSCALE: return (header.width * 1 * header.depth + 7) / 8; - case TRUECOLOR: return (header.width * 3 * header.depth + 7) / 8; - case INDEXED: return (header.width * 1 * header.depth + 7) / 8; - case GRAYSCALE_ALPHA: return (header.width * 2 * header.depth + 7) / 8; - case TRUECOLOR_ALPHA: return (header.width * 4 * header.depth + 7) / 8; - default: abort(); - } + switch (header.color) { + case GRAYSCALE: return (header.width * 1 * header.depth + 7) / 8; + case TRUECOLOR: return (header.width * 3 * header.depth + 7) / 8; + case INDEXED: return (header.width * 1 * header.depth + 7) / 8; + case GRAYSCALE_ALPHA: return (header.width * 2 * header.depth + 7) / 8; + case TRUECOLOR_ALPHA: return (header.width * 4 * header.depth + 7) / 8; + default: abort(); + } } static size_t dataSize(void) { - return (1 + lineSize()) * header.height; + return (1 + lineSize()) * header.height; } static const char *COLOR_STR[] = { - [GRAYSCALE] = "grayscale", - [TRUECOLOR] = "truecolor", - [INDEXED] = "indexed", - [GRAYSCALE_ALPHA] = "grayscale alpha", - [TRUECOLOR_ALPHA] = "truecolor alpha", + [GRAYSCALE] = "grayscale", + [TRUECOLOR] = "truecolor", + [INDEXED] = "indexed", + [GRAYSCALE_ALPHA] = "grayscale alpha", + [TRUECOLOR_ALPHA] = "truecolor alpha", }; static void printHeader(void) { - fprintf( - stderr, - "%s: %ux%u %hhu-bit %s\n", - path, - header.width, header.height, - header.depth, COLOR_STR[header.color] - ); + fprintf( + stderr, + "%s: %ux%u %hhu-bit %s\n", + path, + header.width, header.height, + header.depth, COLOR_STR[header.color] + ); } static void readHeader(void) { - struct Chunk ihdr = readChunk(); - if (0 != memcmp(ihdr.type, "IHDR", 4)) { - errx(EX_DATAERR, "%s: expected IHDR, found %s", path, typeStr(ihdr)); - } - if (ihdr.size != sizeof(header)) { - errx( - EX_DATAERR, "%s: expected IHDR size %zu, found %u", - path, sizeof(header), ihdr.size - ); - } - readExpect(&header, sizeof(header), "header"); - readCrc(); - - header.width = ntohl(header.width); - header.height = ntohl(header.height); - - if (!header.width) errx(EX_DATAERR, "%s: invalid width 0", path); - if (!header.height) errx(EX_DATAERR, "%s: invalid height 0", path); - switch (PAIR(header.color, header.depth)) { - case PAIR(GRAYSCALE, 1): - case PAIR(GRAYSCALE, 2): - case PAIR(GRAYSCALE, 4): - case PAIR(GRAYSCALE, 8): - case PAIR(GRAYSCALE, 16): - case PAIR(TRUECOLOR, 8): - case PAIR(TRUECOLOR, 16): - case PAIR(INDEXED, 1): - case PAIR(INDEXED, 2): - case PAIR(INDEXED, 4): - case PAIR(INDEXED, 8): - case PAIR(GRAYSCALE_ALPHA, 8): - case PAIR(GRAYSCALE_ALPHA, 16): - case PAIR(TRUECOLOR_ALPHA, 8): - case PAIR(TRUECOLOR_ALPHA, 16): - break; - default: - errx( - EX_DATAERR, "%s: invalid color type %hhu and bit depth %hhu", - path, header.color, header.depth - ); - } - if (header.compression != DEFLATE) { - errx( - EX_DATAERR, "%s: invalid compression method %hhu", - path, header.compression - ); - } - if (header.filter != ADAPTIVE) { - errx(EX_DATAERR, "%s: invalid filter method %hhu", path, header.filter); - } - if (header.interlace > ADAM7) { - errx(EX_DATAERR, "%s: invalid interlace method %hhu", path, header.interlace); - } - - if (verbose) printHeader(); + struct Chunk ihdr = readChunk(); + if (0 != memcmp(ihdr.type, "IHDR", 4)) { + errx(EX_DATAERR, "%s: expected IHDR, found %s", path, typeStr(ihdr)); + } + if (ihdr.size != sizeof(header)) { + errx( + EX_DATAERR, "%s: expected IHDR size %zu, found %u", + path, sizeof(header), ihdr.size + ); + } + readExpect(&header, sizeof(header), "header"); + readCrc(); + + header.width = ntohl(header.width); + header.height = ntohl(header.height); + + if (!header.width) errx(EX_DATAERR, "%s: invalid width 0", path); + if (!header.height) errx(EX_DATAERR, "%s: invalid height 0", path); + switch (PAIR(header.color, header.depth)) { + case PAIR(GRAYSCALE, 1): + case PAIR(GRAYSCALE, 2): + case PAIR(GRAYSCALE, 4): + case PAIR(GRAYSCALE, 8): + case PAIR(GRAYSCALE, 16): + case PAIR(TRUECOLOR, 8): + case PAIR(TRUECOLOR, 16): + case PAIR(INDEXED, 1): + case PAIR(INDEXED, 2): + case PAIR(INDEXED, 4): + case PAIR(INDEXED, 8): + case PAIR(GRAYSCALE_ALPHA, 8): + case PAIR(GRAYSCALE_ALPHA, 16): + case PAIR(TRUECOLOR_ALPHA, 8): + case PAIR(TRUECOLOR_ALPHA, 16): + break; + default: + errx( + EX_DATAERR, "%s: invalid color type %hhu and bit depth %hhu", + path, header.color, header.depth + ); + } + if (header.compression != DEFLATE) { + errx( + EX_DATAERR, "%s: invalid compression method %hhu", + path, header.compression + ); + } + if (header.filter != ADAPTIVE) { + errx(EX_DATAERR, "%s: invalid filter method %hhu", path, header.filter); + } + if (header.interlace > ADAM7) { + errx(EX_DATAERR, "%s: invalid interlace method %hhu", path, header.interlace); + } + + if (verbose) printHeader(); } static void writeHeader(void) { - if (verbose) printHeader(); + if (verbose) printHeader(); - struct Chunk ihdr = { .size = sizeof(header), .type = "IHDR" }; - writeChunk(ihdr); - header.width = htonl(header.width); - header.height = htonl(header.height); - writeExpect(&header, sizeof(header)); - writeCrc(); + struct Chunk ihdr = { .size = sizeof(header), .type = "IHDR" }; + writeChunk(ihdr); + header.width = htonl(header.width); + header.height = htonl(header.height); + writeExpect(&header, sizeof(header)); + writeCrc(); - header.width = ntohl(header.width); - header.height = ntohl(header.height); + header.width = ntohl(header.width); + header.height = ntohl(header.height); } static struct { - uint32_t len; - uint8_t entries[256][3]; + uint32_t len; + uint8_t entries[256][3]; } palette; static uint16_t paletteIndex(const uint8_t *rgb) { - uint16_t i; - for (i = 0; i < palette.len; ++i) { - if (0 == memcmp(palette.entries[i], rgb, 3)) break; - } - return i; + uint16_t i; + for (i = 0; i < palette.len; ++i) { + if (0 == memcmp(palette.entries[i], rgb, 3)) break; + } + return i; } static bool paletteAdd(const uint8_t *rgb) { - uint16_t i = paletteIndex(rgb); - if (i < palette.len) return true; - if (i == 256) return false; - memcpy(palette.entries[palette.len++], rgb, 3); - return true; + uint16_t i = paletteIndex(rgb); + if (i < palette.len) return true; + if (i == 256) return false; + memcpy(palette.entries[palette.len++], rgb, 3); + return true; } static void readPalette(void) { - struct Chunk chunk; - for (;;) { - chunk = readChunk(); - if (0 == memcmp(chunk.type, "PLTE", 4)) break; - skipChunk(chunk); - } - if (chunk.size % 3) { - errx(EX_DATAERR, "%s: PLTE size %u not divisible by 3", path, chunk.size); - } + struct Chunk chunk; + for (;;) { + chunk = readChunk(); + if (0 == memcmp(chunk.type, "PLTE", 4)) break; + skipChunk(chunk); + } + if (chunk.size % 3) { + errx(EX_DATAERR, "%s: PLTE size %u not divisible by 3", path, chunk.size); + } - palette.len = chunk.size / 3; - readExpect(palette.entries, chunk.size, "palette data"); - readCrc(); + palette.len = chunk.size / 3; + readExpect(palette.entries, chunk.size, "palette data"); + readCrc(); - if (verbose) fprintf(stderr, "%s: palette length %u\n", path, palette.len); + if (verbose) fprintf(stderr, "%s: palette length %u\n", path, palette.len); } static void writePalette(void) { - if (verbose) fprintf(stderr, "%s: palette length %u\n", path, palette.len); - struct Chunk plte = { .size = 3 * palette.len, .type = "PLTE" }; - writeChunk(plte); - writeExpect(palette.entries, plte.size); - writeCrc(); + if (verbose) fprintf(stderr, "%s: palette length %u\n", path, palette.len); + struct Chunk plte = { .size = 3 * palette.len, .type = "PLTE" }; + writeChunk(plte); + writeExpect(palette.entries, plte.size); + writeCrc(); } static uint8_t *data; static void allocData(void) { - data = malloc(dataSize()); - if (!data) err(EX_OSERR, "malloc(%zu)", dataSize()); + data = malloc(dataSize()); + if (!data) err(EX_OSERR, "malloc(%zu)", dataSize()); } static void readData(void) { - if (verbose) fprintf(stderr, "%s: data size %zu\n", path, dataSize()); - - struct z_stream_s stream = { .next_out = data, .avail_out = dataSize() }; - int error = inflateInit(&stream); - if (error != Z_OK) errx(EX_SOFTWARE, "%s: inflateInit: %s", path, stream.msg); - - for (;;) { - struct Chunk chunk = readChunk(); - if (0 == memcmp(chunk.type, "IDAT", 4)) { - uint8_t idat[chunk.size]; - readExpect(idat, sizeof(idat), "image data"); - readCrc(); - - stream.next_in = idat; - stream.avail_in = sizeof(idat); - int error = inflate(&stream, Z_SYNC_FLUSH); - if (error == Z_STREAM_END) break; - if (error != Z_OK) errx(EX_DATAERR, "%s: inflate: %s", path, stream.msg); - - } else if (0 == memcmp(chunk.type, "IEND", 4)) { - errx(EX_DATAERR, "%s: missing IDAT chunk", path); - } else { - skipChunk(chunk); - } - } - - inflateEnd(&stream); - if (stream.total_out != dataSize()) { - errx( - EX_DATAERR, "%s: expected data size %zu, found %lu", - path, dataSize(), stream.total_out - ); - } - - if (verbose) fprintf(stderr, "%s: deflate size %lu\n", path, stream.total_in); + if (verbose) fprintf(stderr, "%s: data size %zu\n", path, dataSize()); + + struct z_stream_s stream = { .next_out = data, .avail_out = dataSize() }; + int error = inflateInit(&stream); + if (error != Z_OK) errx(EX_SOFTWARE, "%s: inflateInit: %s", path, stream.msg); + + for (;;) { + struct Chunk chunk = readChunk(); + if (0 == memcmp(chunk.type, "IDAT", 4)) { + uint8_t idat[chunk.size]; + readExpect(idat, sizeof(idat), "image data"); + readCrc(); + + stream.next_in = idat; + stream.avail_in = sizeof(idat); + int error = inflate(&stream, Z_SYNC_FLUSH); + if (error == Z_STREAM_END) break; + if (error != Z_OK) errx(EX_DATAERR, "%s: inflate: %s", path, stream.msg); + + } else if (0 == memcmp(chunk.type, "IEND", 4)) { + errx(EX_DATAERR, "%s: missing IDAT chunk", path); + } else { + skipChunk(chunk); + } + } + + inflateEnd(&stream); + if (stream.total_out != dataSize()) { + errx( + EX_DATAERR, "%s: expected data size %zu, found %lu", + path, dataSize(), stream.total_out + ); + } + + if (verbose) fprintf(stderr, "%s: deflate size %lu\n", path, stream.total_in); } static void writeData(void) { - if (verbose) fprintf(stderr, "%s: data size %zu\n", path, dataSize()); + if (verbose) fprintf(stderr, "%s: data size %zu\n", path, dataSize()); - uLong size = compressBound(dataSize()); - uint8_t deflate[size]; - int error = compress2(deflate, &size, data, dataSize(), Z_BEST_COMPRESSION); - if (error != Z_OK) errx(EX_SOFTWARE, "%s: compress2: %d", path, error); + uLong size = compressBound(dataSize()); + uint8_t deflate[size]; + int error = compress2(deflate, &size, data, dataSize(), Z_BEST_COMPRESSION); + if (error != Z_OK) errx(EX_SOFTWARE, "%s: compress2: %d", path, error); - struct Chunk idat = { .size = size, .type = "IDAT" }; - writeChunk(idat); - writeExpect(deflate, size); - writeCrc(); + struct Chunk idat = { .size = size, .type = "IDAT" }; + writeChunk(idat); + writeExpect(deflate, size); + writeCrc(); - if (verbose) fprintf(stderr, "%s: deflate size %lu\n", path, size); + if (verbose) fprintf(stderr, "%s: deflate size %lu\n", path, size); } static void writeEnd(void) { - struct Chunk iend = { .size = 0, .type = "IEND" }; - writeChunk(iend); - writeCrc(); + struct Chunk iend = { .size = 0, .type = "IEND" }; + writeChunk(iend); + writeCrc(); } enum PACKED Filter { - NONE, - SUB, - UP, - AVERAGE, - PAETH, - FILTER_COUNT, + NONE, + SUB, + UP, + AVERAGE, + PAETH, + FILTER_COUNT, }; struct Bytes { - uint8_t x; - uint8_t a; - uint8_t b; - uint8_t c; + uint8_t x; + uint8_t a; + uint8_t b; + uint8_t c; }; static uint8_t paethPredictor(struct Bytes f) { - int32_t p = (int32_t)f.a + (int32_t)f.b - (int32_t)f.c; - int32_t pa = abs(p - (int32_t)f.a); - int32_t pb = abs(p - (int32_t)f.b); - int32_t pc = abs(p - (int32_t)f.c); - if (pa <= pb && pa <= pc) return f.a; - if (pb <= pc) return f.b; - return f.c; + int32_t p = (int32_t)f.a + (int32_t)f.b - (int32_t)f.c; + int32_t pa = abs(p - (int32_t)f.a); + int32_t pb = abs(p - (int32_t)f.b); + int32_t pc = abs(p - (int32_t)f.c); + if (pa <= pb && pa <= pc) return f.a; + if (pb <= pc) return f.b; + return f.c; } static uint8_t recon(enum Filter type, struct Bytes f) { - switch (type) { - case NONE: return f.x; - case SUB: return f.x + f.a; - case UP: return f.x + f.b; - case AVERAGE: return f.x + ((uint32_t)f.a + (uint32_t)f.b) / 2; - case PAETH: return f.x + paethPredictor(f); - default: abort(); - } + switch (type) { + case NONE: return f.x; + case SUB: return f.x + f.a; + case UP: return f.x + f.b; + case AVERAGE: return f.x + ((uint32_t)f.a + (uint32_t)f.b) / 2; + case PAETH: return f.x + paethPredictor(f); + default: abort(); + } } static uint8_t filt(enum Filter type, struct Bytes f) { - switch (type) { - case NONE: return f.x; - case SUB: return f.x - f.a; - case UP: return f.x - f.b; - case AVERAGE: return f.x - ((uint32_t)f.a + (uint32_t)f.b) / 2; - case PAETH: return f.x - paethPredictor(f); - default: abort(); - } + switch (type) { + case NONE: return f.x; + case SUB: return f.x - f.a; + case UP: return f.x - f.b; + case AVERAGE: return f.x - ((uint32_t)f.a + (uint32_t)f.b) / 2; + case PAETH: return f.x - paethPredictor(f); + default: abort(); + } } static struct Line { - enum Filter type; - uint8_t data[]; + enum Filter type; + uint8_t data[]; } **lines; static void allocLines(void) { - lines = calloc(header.height, sizeof(*lines)); - if (!lines) err(EX_OSERR, "calloc(%u, %zu)", header.height, sizeof(*lines)); + lines = calloc(header.height, sizeof(*lines)); + if (!lines) err(EX_OSERR, "calloc(%u, %zu)", header.height, sizeof(*lines)); } static void scanlines(void) { - size_t stride = 1 + lineSize(); - for (uint32_t y = 0; y < header.height; ++y) { - lines[y] = (struct Line *)&data[y * stride]; - if (lines[y]->type >= FILTER_COUNT) { - errx(EX_DATAERR, "%s: invalid filter type %hhu", path, lines[y]->type); - } - } + size_t stride = 1 + lineSize(); + for (uint32_t y = 0; y < header.height; ++y) { + lines[y] = (struct Line *)&data[y * stride]; + if (lines[y]->type >= FILTER_COUNT) { + errx(EX_DATAERR, "%s: invalid filter type %hhu", path, lines[y]->type); + } + } } static struct Bytes origBytes(uint32_t y, size_t i) { - size_t pixelSize = lineSize() / header.width; - if (!pixelSize) pixelSize = 1; - bool a = (i >= pixelSize), b = (y > 0), c = (a && b); - return (struct Bytes) { - .x = lines[y]->data[i], - .a = a ? lines[y]->data[i - pixelSize] : 0, - .b = b ? lines[y - 1]->data[i] : 0, - .c = c ? lines[y - 1]->data[i - pixelSize] : 0, - }; + size_t pixelSize = lineSize() / header.width; + if (!pixelSize) pixelSize = 1; + bool a = (i >= pixelSize), b = (y > 0), c = (a && b); + return (struct Bytes) { + .x = lines[y]->data[i], + .a = a ? lines[y]->data[i - pixelSize] : 0, + .b = b ? lines[y - 1]->data[i] : 0, + .c = c ? lines[y - 1]->data[i - pixelSize] : 0, + }; } static void reconData(void) { - for (uint32_t y = 0; y < header.height; ++y) { - for (size_t i = 0; i < lineSize(); ++i) { - lines[y]->data[i] = - recon(lines[y]->type, origBytes(y, i)); - } - lines[y]->type = NONE; - } + for (uint32_t y = 0; y < header.height; ++y) { + for (size_t i = 0; i < lineSize(); ++i) { + lines[y]->data[i] = + recon(lines[y]->type, origBytes(y, i)); + } + lines[y]->type = NONE; + } } static void filterData(void) { - if (header.color == INDEXED || header.depth < 8) return; - for (uint32_t y = header.height - 1; y < header.height; --y) { - uint8_t filter[FILTER_COUNT][lineSize()]; - uint32_t heuristic[FILTER_COUNT] = {0}; - enum Filter minType = NONE; - for (enum Filter type = NONE; type < FILTER_COUNT; ++type) { - for (size_t i = 0; i < lineSize(); ++i) { - filter[type][i] = filt(type, origBytes(y, i)); - heuristic[type] += abs((int8_t)filter[type][i]); - } - if (heuristic[type] < heuristic[minType]) minType = type; - } - lines[y]->type = minType; - memcpy(lines[y]->data, filter[minType], lineSize()); - } + if (header.color == INDEXED || header.depth < 8) return; + for (uint32_t y = header.height - 1; y < header.height; --y) { + uint8_t filter[FILTER_COUNT][lineSize()]; + uint32_t heuristic[FILTER_COUNT] = {0}; + enum Filter minType = NONE; + for (enum Filter type = NONE; type < FILTER_COUNT; ++type) { + for (size_t i = 0; i < lineSize(); ++i) { + filter[type][i] = filt(type, origBytes(y, i)); + heuristic[type] += abs((int8_t)filter[type][i]); + } + if (heuristic[type] < heuristic[minType]) minType = type; + } + lines[y]->type = minType; + memcpy(lines[y]->data, filter[minType], lineSize()); + } } static void discardAlpha(void) { - if (header.color != GRAYSCALE_ALPHA && header.color != TRUECOLOR_ALPHA) return; - size_t sampleSize = header.depth / 8; - size_t pixelSize = sampleSize * (header.color == GRAYSCALE_ALPHA ? 2 : 4); - size_t colorSize = pixelSize - sampleSize; - for (uint32_t y = 0; y < header.height; ++y) { - for (uint32_t x = 0; x < header.width; ++x) { - for (size_t i = 0; i < sampleSize; ++i) { - if (lines[y]->data[x * pixelSize + colorSize + i] != 0xFF) return; - } - } - } - - uint8_t *ptr = data; - for (uint32_t y = 0; y < header.height; ++y) { - *ptr++ = lines[y]->type; - for (uint32_t x = 0; x < header.width; ++x) { - memmove(ptr, &lines[y]->data[x * pixelSize], colorSize); - ptr += colorSize; - } - } - header.color = (header.color == GRAYSCALE_ALPHA) ? GRAYSCALE : TRUECOLOR; - scanlines(); + if (header.color != GRAYSCALE_ALPHA && header.color != TRUECOLOR_ALPHA) return; + size_t sampleSize = header.depth / 8; + size_t pixelSize = sampleSize * (header.color == GRAYSCALE_ALPHA ? 2 : 4); + size_t colorSize = pixelSize - sampleSize; + for (uint32_t y = 0; y < header.height; ++y) { + for (uint32_t x = 0; x < header.width; ++x) { + for (size_t i = 0; i < sampleSize; ++i) { + if (lines[y]->data[x * pixelSize + colorSize + i] != 0xFF) return; + } + } + } + + uint8_t *ptr = data; + for (uint32_t y = 0; y < header.height; ++y) { + *ptr++ = lines[y]->type; + for (uint32_t x = 0; x < header.width; ++x) { + memmove(ptr, &lines[y]->data[x * pixelSize], colorSize); + ptr += colorSize; + } + } + header.color = (header.color == GRAYSCALE_ALPHA) ? GRAYSCALE : TRUECOLOR; + scanlines(); } static void discardColor(void) { - if (header.color != TRUECOLOR && header.color != TRUECOLOR_ALPHA) return; - size_t sampleSize = header.depth / 8; - size_t pixelSize = sampleSize * (header.color == TRUECOLOR ? 3 : 4); - for (uint32_t y = 0; y < header.height; ++y) { - for (uint32_t x = 0; x < header.width; ++x) { - uint8_t *r = &lines[y]->data[x * pixelSize]; - uint8_t *g = r + sampleSize; - uint8_t *b = g + sampleSize; - if (0 != memcmp(r, g, sampleSize)) return; - if (0 != memcmp(g, b, sampleSize)) return; - } - } - - uint8_t *ptr = data; - for (uint32_t y = 0; y < header.height; ++y) { - *ptr++ = lines[y]->type; - for (uint32_t x = 0; x < header.width; ++x) { - uint8_t *pixel = &lines[y]->data[x * pixelSize]; - memmove(ptr, pixel, sampleSize); - ptr += sampleSize; - if (header.color == TRUECOLOR_ALPHA) { - memmove(ptr, pixel + 3 * sampleSize, sampleSize); - ptr += sampleSize; - } - } - } - header.color = (header.color == TRUECOLOR) ? GRAYSCALE : GRAYSCALE_ALPHA; - scanlines(); + if (header.color != TRUECOLOR && header.color != TRUECOLOR_ALPHA) return; + size_t sampleSize = header.depth / 8; + size_t pixelSize = sampleSize * (header.color == TRUECOLOR ? 3 : 4); + for (uint32_t y = 0; y < header.height; ++y) { + for (uint32_t x = 0; x < header.width; ++x) { + uint8_t *r = &lines[y]->data[x * pixelSize]; + uint8_t *g = r + sampleSize; + uint8_t *b = g + sampleSize; + if (0 != memcmp(r, g, sampleSize)) return; + if (0 != memcmp(g, b, sampleSize)) return; + } + } + + uint8_t *ptr = data; + for (uint32_t y = 0; y < header.height; ++y) { + *ptr++ = lines[y]->type; + for (uint32_t x = 0; x < header.width; ++x) { + uint8_t *pixel = &lines[y]->data[x * pixelSize]; + memmove(ptr, pixel, sampleSize); + ptr += sampleSize; + if (header.color == TRUECOLOR_ALPHA) { + memmove(ptr, pixel + 3 * sampleSize, sampleSize); + ptr += sampleSize; + } + } + } + header.color = (header.color == TRUECOLOR) ? GRAYSCALE : GRAYSCALE_ALPHA; + scanlines(); } static void indexColor(void) { - if (header.color != TRUECOLOR || header.depth != 8) return; - for (uint32_t y = 0; y < header.height; ++y) { - for (uint32_t x = 0; x < header.width; ++x) { - if (!paletteAdd(&lines[y]->data[x * 3])) return; - } - } - - uint8_t *ptr = data; - for (uint32_t y = 0; y < header.height; ++y) { - *ptr++ = lines[y]->type; - for (uint32_t x = 0; x < header.width; ++x) { - *ptr++ = paletteIndex(&lines[y]->data[x * 3]); - } - } - header.color = INDEXED; - scanlines(); + if (header.color != TRUECOLOR || header.depth != 8) return; + for (uint32_t y = 0; y < header.height; ++y) { + for (uint32_t x = 0; x < header.width; ++x) { + if (!paletteAdd(&lines[y]->data[x * 3])) return; + } + } + + uint8_t *ptr = data; + for (uint32_t y = 0; y < header.height; ++y) { + *ptr++ = lines[y]->type; + for (uint32_t x = 0; x < header.width; ++x) { + *ptr++ = paletteIndex(&lines[y]->data[x * 3]); + } + } + header.color = INDEXED; + scanlines(); } static void reduceDepth8(void) { - if (header.color != GRAYSCALE && header.color != INDEXED) return; - if (header.depth != 8) return; - if (header.color == GRAYSCALE) { - for (uint32_t y = 0; y < header.height; ++y) { - for (size_t i = 0; i < lineSize(); ++i) { - uint8_t a = lines[y]->data[i]; - if ((a >> 4) != (a & 0x0F)) return; - } - } - } else if (palette.len > 16) { - return; - } - - uint8_t *ptr = data; - for (uint32_t y = 0; y < header.height; ++y) { - *ptr++ = lines[y]->type; - for (size_t i = 0; i < lineSize(); i += 2) { - uint8_t iByte = lines[y]->data[i]; - uint8_t jByte = (i + 1 < lineSize()) ? lines[y]->data[i + 1] : 0; - uint8_t a = iByte & 0x0F; - uint8_t b = jByte & 0x0F; - *ptr++ = a << 4 | b; - } - } - header.depth = 4; - scanlines(); + if (header.color != GRAYSCALE && header.color != INDEXED) return; + if (header.depth != 8) return; + if (header.color == GRAYSCALE) { + for (uint32_t y = 0; y < header.height; ++y) { + for (size_t i = 0; i < lineSize(); ++i) { + uint8_t a = lines[y]->data[i]; + if ((a >> 4) != (a & 0x0F)) return; + } + } + } else if (palette.len > 16) { + return; + } + + uint8_t *ptr = data; + for (uint32_t y = 0; y < header.height; ++y) { + *ptr++ = lines[y]->type; + for (size_t i = 0; i < lineSize(); i += 2) { + uint8_t iByte = lines[y]->data[i]; + uint8_t jByte = (i + 1 < lineSize()) ? lines[y]->data[i + 1] : 0; + uint8_t a = iByte & 0x0F; + uint8_t b = jByte & 0x0F; + *ptr++ = a << 4 | b; + } + } + header.depth = 4; + scanlines(); } static void reduceDepth4(void) { - if (header.depth != 4) return; - if (header.color == GRAYSCALE) { - for (uint32_t y = 0; y < header.height; ++y) { - for (size_t i = 0; i < lineSize(); ++i) { - uint8_t a = lines[y]->data[i] >> 4; - uint8_t b = lines[y]->data[i] & 0x0F; - if ((a >> 2) != (a & 0x03)) return; - if ((b >> 2) != (b & 0x03)) return; - } - } - } else if (palette.len > 4) { - return; - } - - uint8_t *ptr = data; - for (uint32_t y = 0; y < header.height; ++y) { - *ptr++ = lines[y]->type; - for (size_t i = 0; i < lineSize(); i += 2) { - uint8_t iByte = lines[y]->data[i]; - uint8_t jByte = (i + 1 < lineSize()) ? lines[y]->data[i + 1] : 0; - uint8_t a = iByte >> 4 & 0x03, b = iByte & 0x03; - uint8_t c = jByte >> 4 & 0x03, d = jByte & 0x03; - *ptr++ = a << 6 | b << 4 | c << 2 | d; - } - } - header.depth = 2; - scanlines(); + if (header.depth != 4) return; + if (header.color == GRAYSCALE) { + for (uint32_t y = 0; y < header.height; ++y) { + for (size_t i = 0; i < lineSize(); ++i) { + uint8_t a = lines[y]->data[i] >> 4; + uint8_t b = lines[y]->data[i] & 0x0F; + if ((a >> 2) != (a & 0x03)) return; + if ((b >> 2) != (b & 0x03)) return; + } + } + } else if (palette.len > 4) { + return; + } + + uint8_t *ptr = data; + for (uint32_t y = 0; y < header.height; ++y) { + *ptr++ = lines[y]->type; + for (size_t i = 0; i < lineSize(); i += 2) { + uint8_t iByte = lines[y]->data[i]; + uint8_t jByte = (i + 1 < lineSize()) ? lines[y]->data[i + 1] : 0; + uint8_t a = iByte >> 4 & 0x03, b = iByte & 0x03; + uint8_t c = jByte >> 4 & 0x03, d = jByte & 0x03; + *ptr++ = a << 6 | b << 4 | c << 2 | d; + } + } + header.depth = 2; + scanlines(); } static void reduceDepth2(void) { - if (header.depth != 2) return; - if (header.color == GRAYSCALE) { - for (uint32_t y = 0; y < header.height; ++y) { - for (size_t i = 0; i < lineSize(); ++i) { - uint8_t a = lines[y]->data[i] >> 6; - uint8_t b = lines[y]->data[i] >> 4 & 0x03; - uint8_t c = lines[y]->data[i] >> 2 & 0x03; - uint8_t d = lines[y]->data[i] & 0x03; - if ((a >> 1) != (a & 0x01)) return; - if ((b >> 1) != (b & 0x01)) return; - if ((c >> 1) != (c & 0x01)) return; - if ((d >> 1) != (d & 0x01)) return; - } - } - } else if (palette.len > 2) { - return; - } - - uint8_t *ptr = data; - for (uint32_t y = 0; y < header.height; ++y) { - *ptr++ = lines[y]->type; - for (size_t i = 0; i < lineSize(); i += 2) { - uint8_t iByte = lines[y]->data[i]; - uint8_t jByte = (i + 1 < lineSize()) ? lines[y]->data[i + 1] : 0; - uint8_t a = iByte >> 6 & 0x01, b = iByte >> 4 & 0x01; - uint8_t c = iByte >> 2 & 0x01, d = iByte & 0x01; - uint8_t e = jByte >> 6 & 0x01, f = jByte >> 4 & 0x01; - uint8_t g = jByte >> 2 & 0x01, h = jByte & 0x01; - *ptr++ = a << 7 | b << 6 | c << 5 | d << 4 | e << 3 | f << 2 | g << 1 | h; - } - } - header.depth = 1; - scanlines(); + if (header.depth != 2) return; + if (header.color == GRAYSCALE) { + for (uint32_t y = 0; y < header.height; ++y) { + for (size_t i = 0; i < lineSize(); ++i) { + uint8_t a = lines[y]->data[i] >> 6; + uint8_t b = lines[y]->data[i] >> 4 & 0x03; + uint8_t c = lines[y]->data[i] >> 2 & 0x03; + uint8_t d = lines[y]->data[i] & 0x03; + if ((a >> 1) != (a & 0x01)) return; + if ((b >> 1) != (b & 0x01)) return; + if ((c >> 1) != (c & 0x01)) return; + if ((d >> 1) != (d & 0x01)) return; + } + } + } else if (palette.len > 2) { + return; + } + + uint8_t *ptr = data; + for (uint32_t y = 0; y < header.height; ++y) { + *ptr++ = lines[y]->type; + for (size_t i = 0; i < lineSize(); i += 2) { + uint8_t iByte = lines[y]->data[i]; + uint8_t jByte = (i + 1 < lineSize()) ? lines[y]->data[i + 1] : 0; + uint8_t a = iByte >> 6 & 0x01, b = iByte >> 4 & 0x01; + uint8_t c = iByte >> 2 & 0x01, d = iByte & 0x01; + uint8_t e = jByte >> 6 & 0x01, f = jByte >> 4 & 0x01; + uint8_t g = jByte >> 2 & 0x01, h = jByte & 0x01; + *ptr++ = a << 7 | b << 6 | c << 5 | d << 4 | e << 3 | f << 2 | g << 1 | h; + } + } + header.depth = 1; + scanlines(); } static void reduceDepth(void) { - reduceDepth8(); - reduceDepth4(); - reduceDepth2(); + reduceDepth8(); + reduceDepth4(); + reduceDepth2(); } static void optimize(const char *inPath, const char *outPath) { - if (inPath) { - path = inPath; - file = fopen(path, "r"); - if (!file) err(EX_NOINPUT, "%s", path); - } else { - path = "(stdin)"; - file = stdin; - } - - readSignature(); - readHeader(); - if (header.interlace != PROGRESSIVE) { - errx( - EX_CONFIG, "%s: unsupported interlace method %hhu", - path, header.interlace - ); - } - if (header.color == INDEXED) readPalette(); - allocData(); - readData(); - fclose(file); - - allocLines(); - scanlines(); - reconData(); - - discardAlpha(); - discardColor(); - indexColor(); - reduceDepth(); - filterData(); - free(lines); - - if (outPath) { - path = outPath; - file = fopen(path, "w"); - if (!file) err(EX_CANTCREAT, "%s", path); - } else { - path = "(stdout)"; - file = stdout; - } - - writeSignature(); - writeHeader(); - if (header.color == INDEXED) writePalette(); - writeData(); - writeEnd(); - free(data); - - int error = fclose(file); - if (error) err(EX_IOERR, "%s", path); + if (inPath) { + path = inPath; + file = fopen(path, "r"); + if (!file) err(EX_NOINPUT, "%s", path); + } else { + path = "(stdin)"; + file = stdin; + } + + readSignature(); + readHeader(); + if (header.interlace != PROGRESSIVE) { + errx( + EX_CONFIG, "%s: unsupported interlace method %hhu", + path, header.interlace + ); + } + if (header.color == INDEXED) readPalette(); + allocData(); + readData(); + fclose(file); + + allocLines(); + scanlines(); + reconData(); + + discardAlpha(); + discardColor(); + indexColor(); + reduceDepth(); + filterData(); + free(lines); + + if (outPath) { + path = outPath; + file = fopen(path, "w"); + if (!file) err(EX_CANTCREAT, "%s", path); + } else { + path = "(stdout)"; + file = stdout; + } + + writeSignature(); + writeHeader(); + if (header.color == INDEXED) writePalette(); + writeData(); + writeEnd(); + free(data); + + int error = fclose(file); + if (error) err(EX_IOERR, "%s", path); } int main(int argc, char *argv[]) { - bool stdio = false; - char *output = NULL; - - int opt; - while (0 < (opt = getopt(argc, argv, "co:v"))) { - switch (opt) { - case 'c': stdio = true; break; - case 'o': output = optarg; break; - case 'v': verbose = true; break; - default: return EX_USAGE; - } - } - - if (argc - optind == 1 && (output || stdio)) { - optimize(argv[optind], output); - } else if (optind < argc) { - for (int i = optind; i < argc; ++i) { - optimize(argv[i], argv[i]); - } - } else { - optimize(NULL, output); - } - - return EX_OK; + bool stdio = false; + char *output = NULL; + + int opt; + while (0 < (opt = getopt(argc, argv, "co:v"))) { + switch (opt) { + case 'c': stdio = true; break; + case 'o': output = optarg; break; + case 'v': verbose = true; break; + default: return EX_USAGE; + } + } + + if (argc - optind == 1 && (output || stdio)) { + optimize(argv[optind], output); + } else if (optind < argc) { + for (int i = optind; i < argc; ++i) { + optimize(argv[i], argv[i]); + } + } else { + optimize(NULL, output); + } + + return EX_OK; } diff --git a/bin/scheme.c b/bin/scheme.c index f3a386a8..b43e4fec 100644 --- a/bin/scheme.c +++ b/bin/scheme.c @@ -26,194 +26,194 @@ #include <zlib.h> static const struct Hsv { double h, s, v; } - R = { 0.0, 1.0, 1.0 }, - Y = { 60.0, 1.0, 1.0 }, - G = { 120.0, 1.0, 1.0 }, - C = { 180.0, 1.0, 1.0 }, - B = { 240.0, 1.0, 1.0 }, - M = { 300.0, 1.0, 1.0 }; +R = { 0.0, 1.0, 1.0 }, + Y = { 60.0, 1.0, 1.0 }, + G = { 120.0, 1.0, 1.0 }, + C = { 180.0, 1.0, 1.0 }, + B = { 240.0, 1.0, 1.0 }, + M = { 300.0, 1.0, 1.0 }; static struct Hsv x(struct Hsv o, double hd, double sf, double vf) { - return (struct Hsv) { - fmod(o.h + hd, 360.0), - fmin(o.s * sf, 1.0), - fmin(o.v * vf, 1.0), - }; + return (struct Hsv) { + fmod(o.h + hd, 360.0), + fmin(o.s * sf, 1.0), + fmin(o.v * vf, 1.0), + }; } struct Ansi { - enum { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE }; - struct Hsv dark[8]; - struct Hsv light[8]; + enum { BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE }; + struct Hsv dark[8]; + struct Hsv light[8]; }; struct Terminal { - struct Ansi ansi; - struct Hsv background, text, bold, selection, cursor; + struct Ansi ansi; + struct Hsv background, text, bold, selection, cursor; }; #define HSV_LEN(x) (sizeof(x) / sizeof(struct Hsv)) struct Scheme { - size_t len; - union { - struct Hsv hsv; - struct Ansi ansi; - struct Terminal terminal; - }; + size_t len; + union { + struct Hsv hsv; + struct Ansi ansi; + struct Terminal terminal; + }; }; static struct Scheme ansi(void) { - struct Ansi a = { - .light = { - [BLACK] = x(R, +45.0, 0.3, 0.3), - [RED] = x(R, +10.0, 0.9, 0.8), - [GREEN] = x(G, -55.0, 0.8, 0.6), - [YELLOW] = x(Y, -20.0, 0.8, 0.8), - [BLUE] = x(B, -55.0, 0.4, 0.5), - [MAGENTA] = x(M, +45.0, 0.4, 0.6), - [CYAN] = x(C, -60.0, 0.3, 0.6), - [WHITE] = x(R, +45.0, 0.3, 0.8), - }, - }; - a.dark[BLACK] = x(a.light[BLACK], 0.0, 1.0, 0.3); - a.dark[WHITE] = x(a.light[WHITE], 0.0, 1.0, 0.6); - for (int i = RED; i < WHITE; ++i) { - a.dark[i] = x(a.light[i], 0.0, 1.0, 0.8); - } - return (struct Scheme) { .len = HSV_LEN(a), .ansi = a }; + struct Ansi a = { + .light = { + [BLACK] = x(R, +45.0, 0.3, 0.3), + [RED] = x(R, +10.0, 0.9, 0.8), + [GREEN] = x(G, -55.0, 0.8, 0.6), + [YELLOW] = x(Y, -20.0, 0.8, 0.8), + [BLUE] = x(B, -55.0, 0.4, 0.5), + [MAGENTA] = x(M, +45.0, 0.4, 0.6), + [CYAN] = x(C, -60.0, 0.3, 0.6), + [WHITE] = x(R, +45.0, 0.3, 0.8), + }, + }; + a.dark[BLACK] = x(a.light[BLACK], 0.0, 1.0, 0.3); + a.dark[WHITE] = x(a.light[WHITE], 0.0, 1.0, 0.6); + for (int i = RED; i < WHITE; ++i) { + a.dark[i] = x(a.light[i], 0.0, 1.0, 0.8); + } + return (struct Scheme) { .len = HSV_LEN(a), .ansi = a }; } static struct Scheme terminal(void) { - struct Ansi a = ansi().ansi; - struct Terminal t = { - .ansi = a, - .background = x(a.dark[BLACK], 0.0, 1.0, 0.9), - .text = x(a.light[WHITE], 0.0, 1.0, 0.9), - .bold = x(a.light[WHITE], 0.0, 1.0, 1.0), - .selection = x(a.light[RED], +10.0, 1.0, 0.8), - .cursor = x(a.dark[WHITE], 0.0, 1.0, 0.8), - }; - return (struct Scheme) { .len = HSV_LEN(t), .terminal = t }; + struct Ansi a = ansi().ansi; + struct Terminal t = { + .ansi = a, + .background = x(a.dark[BLACK], 0.0, 1.0, 0.9), + .text = x(a.light[WHITE], 0.0, 1.0, 0.9), + .bold = x(a.light[WHITE], 0.0, 1.0, 1.0), + .selection = x(a.light[RED], +10.0, 1.0, 0.8), + .cursor = x(a.dark[WHITE], 0.0, 1.0, 0.8), + }; + return (struct Scheme) { .len = HSV_LEN(t), .terminal = t }; } static void hsv(const struct Hsv *hsv, size_t len) { - for (size_t i = 0; i < len; ++i) { - printf("%g,%g,%g\n", hsv[i].h, hsv[i].s, hsv[i].v); - } + for (size_t i = 0; i < len; ++i) { + printf("%g,%g,%g\n", hsv[i].h, hsv[i].s, hsv[i].v); + } } struct Rgb { uint8_t r, g, b; }; static struct Rgb toRgb(struct Hsv hsv) { - double c = hsv.v * hsv.s; - double h = hsv.h / 60.0; - double x = c * (1.0 - fabs(fmod(h, 2.0) - 1.0)); - double m = hsv.v - c; - double r = m, g = m, b = m; - if (h <= 1.0) { r += c; g += x; } - else if (h <= 2.0) { r += x; g += c; } - else if (h <= 3.0) { g += c; b += x; } - else if (h <= 4.0) { g += x; b += c; } - else if (h <= 5.0) { r += x; b += c; } - else if (h <= 6.0) { r += c; b += x; } - return (struct Rgb) { r * 255.0, g * 255.0, b * 255.0 }; + double c = hsv.v * hsv.s; + double h = hsv.h / 60.0; + double x = c * (1.0 - fabs(fmod(h, 2.0) - 1.0)); + double m = hsv.v - c; + double r = m, g = m, b = m; + if (h <= 1.0) { r += c; g += x; } + else if (h <= 2.0) { r += x; g += c; } + else if (h <= 3.0) { g += c; b += x; } + else if (h <= 4.0) { g += x; b += c; } + else if (h <= 5.0) { r += x; b += c; } + else if (h <= 6.0) { r += c; b += x; } + return (struct Rgb) { r * 255.0, g * 255.0, b * 255.0 }; } static void hex(const struct Hsv *hsv, size_t len) { - for (size_t i = 0; i < len; ++i) { - struct Rgb rgb = toRgb(hsv[i]); - printf("%02X%02X%02X\n", rgb.r, rgb.g, rgb.b); - } + for (size_t i = 0; i < len; ++i) { + struct Rgb rgb = toRgb(hsv[i]); + printf("%02X%02X%02X\n", rgb.r, rgb.g, rgb.b); + } } static void linux(const struct Hsv *hsv, size_t len) { - if (len > 16) len = 16; - for (size_t i = 0; i < len; ++i) { - struct Rgb rgb = toRgb(hsv[i]); - printf("\x1B]P%zX%02X%02X%02X", i, rgb.r, rgb.g, rgb.b); - } + if (len > 16) len = 16; + for (size_t i = 0; i < len; ++i) { + struct Rgb rgb = toRgb(hsv[i]); + printf("\x1B]P%zX%02X%02X%02X", i, rgb.r, rgb.g, rgb.b); + } } static uint32_t crc; static void pngWrite(const void *ptr, size_t size) { - fwrite(ptr, size, 1, stdout); - if (ferror(stdout)) err(EX_IOERR, "(stdout)"); - crc = crc32(crc, ptr, size); + fwrite(ptr, size, 1, stdout); + if (ferror(stdout)) err(EX_IOERR, "(stdout)"); + crc = crc32(crc, ptr, size); } static void pngInt(uint32_t host) { - uint32_t net = htonl(host); - pngWrite(&net, 4); + uint32_t net = htonl(host); + pngWrite(&net, 4); } static void pngChunk(const char *type, uint32_t size) { - pngInt(size); - crc = crc32(0, Z_NULL, 0); - pngWrite(type, 4); + pngInt(size); + crc = crc32(0, Z_NULL, 0); + pngWrite(type, 4); } static void png(const struct Hsv *hsv, size_t len) { - if (len > 256) len = 256; - uint32_t swatchWidth = 64; - uint32_t swatchHeight = 64; - uint32_t columns = 8; - uint32_t rows = (len + columns - 1) / columns; - uint32_t width = swatchWidth * columns; - uint32_t height = swatchHeight * rows; - - pngWrite("\x89PNG\r\n\x1A\n", 8); - - pngChunk("IHDR", 13); - pngInt(width); - pngInt(height); - pngWrite("\x08\x03\0\0\0", 5); - pngInt(crc); - - pngChunk("PLTE", 3 * len); - for (size_t i = 0; i < len; ++i) { - struct Rgb rgb = toRgb(hsv[i]); - pngWrite(&rgb, 3); - } - pngInt(crc); - - uint8_t data[height][1 + width]; - memset(data, 0, sizeof(data)); - for (uint32_t y = 0; y < height; ++y) { - enum { NONE, SUB, UP, AVERAGE, PAETH }; - data[y][0] = (y % swatchHeight) ? UP : SUB; - } - for (size_t i = 0; i < len; ++i) { - uint32_t y = swatchHeight * (i / columns); - uint32_t x = swatchWidth * (i % columns); - data[y][1 + x] = x ? 1 : i; - } - - uLong size = compressBound(sizeof(data)); - uint8_t deflate[size]; - int error = compress(deflate, &size, (Byte *)data, sizeof(data)); - if (error != Z_OK) errx(EX_SOFTWARE, "compress: %d", error); - - pngChunk("IDAT", size); - pngWrite(deflate, size); - pngInt(crc); - - pngChunk("IEND", 0); - pngInt(crc); + if (len > 256) len = 256; + uint32_t swatchWidth = 64; + uint32_t swatchHeight = 64; + uint32_t columns = 8; + uint32_t rows = (len + columns - 1) / columns; + uint32_t width = swatchWidth * columns; + uint32_t height = swatchHeight * rows; + + pngWrite("\x89PNG\r\n\x1A\n", 8); + + pngChunk("IHDR", 13); + pngInt(width); + pngInt(height); + pngWrite("\x08\x03\0\0\0", 5); + pngInt(crc); + + pngChunk("PLTE", 3 * len); + for (size_t i = 0; i < len; ++i) { + struct Rgb rgb = toRgb(hsv[i]); + pngWrite(&rgb, 3); + } + pngInt(crc); + + uint8_t data[height][1 + width]; + memset(data, 0, sizeof(data)); + for (uint32_t y = 0; y < height; ++y) { + enum { NONE, SUB, UP, AVERAGE, PAETH }; + data[y][0] = (y % swatchHeight) ? UP : SUB; + } + for (size_t i = 0; i < len; ++i) { + uint32_t y = swatchHeight * (i / columns); + uint32_t x = swatchWidth * (i % columns); + data[y][1 + x] = x ? 1 : i; + } + + uLong size = compressBound(sizeof(data)); + uint8_t deflate[size]; + int error = compress(deflate, &size, (Byte *)data, sizeof(data)); + if (error != Z_OK) errx(EX_SOFTWARE, "compress: %d", error); + + pngChunk("IDAT", size); + pngWrite(deflate, size); + pngInt(crc); + + pngChunk("IEND", 0); + pngInt(crc); } int main(int argc, char *argv[]) { - struct Scheme (*gen)(void) = ansi; - void (*out)(const struct Hsv *, size_t len) = hex; - int opt; - while (0 < (opt = getopt(argc, argv, "aghltx"))) { - switch (opt) { - case 'a': gen = ansi; break; - case 'g': out = png; break; - case 'h': out = hsv; break; - case 'l': out = linux; break; - case 't': gen = terminal; break; - case 'x': out = hex; break; - default: return EX_USAGE; - } - } - struct Scheme scheme = gen(); - out(&scheme.hsv, scheme.len); - return EX_OK; + struct Scheme (*gen)(void) = ansi; + void (*out)(const struct Hsv *, size_t len) = hex; + int opt; + while (0 < (opt = getopt(argc, argv, "aghltx"))) { + switch (opt) { + case 'a': gen = ansi; break; + case 'g': out = png; break; + case 'h': out = hsv; break; + case 'l': out = linux; break; + case 't': gen = terminal; break; + case 'x': out = hex; break; + default: return EX_USAGE; + } + } + struct Scheme scheme = gen(); + out(&scheme.hsv, scheme.len); + return EX_OK; } diff --git a/bin/wake.c b/bin/wake.c index 3cfb5b38..205c202c 100644 --- a/bin/wake.c +++ b/bin/wake.c @@ -25,29 +25,29 @@ #define MAC 0x04, 0x7D, 0x7B, 0xD5, 0x6A, 0x53 static const uint8_t payload[102] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - MAC, MAC, MAC, MAC, MAC, MAC, MAC, MAC, - MAC, MAC, MAC, MAC, MAC, MAC, MAC, MAC, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + MAC, MAC, MAC, MAC, MAC, MAC, MAC, MAC, + MAC, MAC, MAC, MAC, MAC, MAC, MAC, MAC, }; int main() { - int sock = socket(PF_INET, SOCK_DGRAM, 0); - if (sock < 0) err(EX_OSERR, "socket"); + int sock = socket(PF_INET, SOCK_DGRAM, 0); + if (sock < 0) err(EX_OSERR, "socket"); - int on = 1; - int error = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); - if (error) err(EX_OSERR, "setsockopt"); + int on = 1; + int error = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)); + if (error) err(EX_OSERR, "setsockopt"); - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_port = 9, - .sin_addr.s_addr = INADDR_BROADCAST, - }; - ssize_t size = sendto( - sock, payload, sizeof(payload), 0, - (struct sockaddr *)&addr, sizeof(addr) - ); - if (size < 0) err(EX_IOERR, "sendto"); + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = 9, + .sin_addr.s_addr = INADDR_BROADCAST, + }; + ssize_t size = sendto( + sock, payload, sizeof(payload), 0, + (struct sockaddr *)&addr, sizeof(addr) + ); + if (size < 0) err(EX_IOERR, "sendto"); - return EX_OK; + return EX_OK; } diff --git a/bin/watch.c b/bin/watch.c index f33c9ee7..3308edc9 100644 --- a/bin/watch.c +++ b/bin/watch.c @@ -25,70 +25,70 @@ #include <unistd.h> static void watch(int kq, char *path) { - int fd = open(path, O_CLOEXEC); - if (fd < 0) err(EX_NOINPUT, "%s", path); + int fd = open(path, O_CLOEXEC); + if (fd < 0) err(EX_NOINPUT, "%s", path); - struct kevent event = { - .ident = fd, - .filter = EVFILT_VNODE, - .flags = EV_ADD | EV_CLEAR, - .fflags = NOTE_WRITE | NOTE_DELETE, - .udata = path, - }; - int nevents = kevent(kq, &event, 1, NULL, 0, NULL); - if (nevents < 0) err(EX_OSERR, "kevent"); + struct kevent event = { + .ident = fd, + .filter = EVFILT_VNODE, + .flags = EV_ADD | EV_CLEAR, + .fflags = NOTE_WRITE | NOTE_DELETE, + .udata = path, + }; + int nevents = kevent(kq, &event, 1, NULL, 0, NULL); + if (nevents < 0) err(EX_OSERR, "kevent"); } static void exec(char *const argv[]) { - pid_t pid = fork(); - if (pid < 0) err(EX_OSERR, "fork"); + pid_t pid = fork(); + if (pid < 0) err(EX_OSERR, "fork"); - if (!pid) { - execvp(*argv, argv); - err(EX_NOINPUT, "%s", *argv); - } + if (!pid) { + execvp(*argv, argv); + err(EX_NOINPUT, "%s", *argv); + } - int status; - pid = wait(&status); - if (pid < 0) err(EX_OSERR, "wait"); + int status; + pid = wait(&status); + if (pid < 0) err(EX_OSERR, "wait"); - if (WIFEXITED(status)) { - warnx("exit %d\n", WEXITSTATUS(status)); - } else if (WIFSIGNALED(status)) { - warnx("signal %d\n", WTERMSIG(status)); - } else { - warnx("status %d\n", status); - } + if (WIFEXITED(status)) { + warnx("exit %d\n", WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + warnx("signal %d\n", WTERMSIG(status)); + } else { + warnx("status %d\n", status); + } } int main(int argc, char *argv[]) { - if (argc < 3) return EX_USAGE; + if (argc < 3) return EX_USAGE; - int kq = kqueue(); - if (kq < 0) err(EX_OSERR, "kqueue"); + int kq = kqueue(); + if (kq < 0) err(EX_OSERR, "kqueue"); - int i; - for (i = 1; i < argc - 1; ++i) { - if (argv[i][0] == '-') { - i++; - break; - } - watch(kq, argv[i]); - } + int i; + for (i = 1; i < argc - 1; ++i) { + if (argv[i][0] == '-') { + i++; + break; + } + watch(kq, argv[i]); + } - exec(&argv[i]); + exec(&argv[i]); - for (;;) { - struct kevent event; - int nevents = kevent(kq, NULL, 0, &event, 1, NULL); - if (nevents < 0) err(EX_OSERR, "kevent"); + for (;;) { + struct kevent event; + int nevents = kevent(kq, NULL, 0, &event, 1, NULL); + if (nevents < 0) err(EX_OSERR, "kevent"); - if (event.fflags & NOTE_DELETE) { - close(event.ident); - sleep(1); - watch(kq, event.udata); - } + if (event.fflags & NOTE_DELETE) { + close(event.ident); + sleep(1); + watch(kq, event.udata); + } - exec(&argv[i]); - } + exec(&argv[i]); + } } diff --git a/bin/xx.c b/bin/xx.c index 82e00b43..663ee044 100644 --- a/bin/xx.c +++ b/bin/xx.c @@ -24,110 +24,110 @@ #include <unistd.h> static bool zero(const uint8_t *ptr, size_t size) { - for (size_t i = 0; i < size; ++i) { - if (ptr[i]) return false; - } - return true; + for (size_t i = 0; i < size; ++i) { + if (ptr[i]) return false; + } + return true; } static struct { - size_t cols; - size_t group; - bool ascii; - bool offset; - bool skip; + size_t cols; + size_t group; + bool ascii; + bool offset; + bool skip; } options = { 16, 8, true, true, false }; static void dump(FILE *file) { - bool skip = false; + bool skip = false; - uint8_t buf[options.cols]; - size_t offset = 0; - for ( - size_t size; - (size = fread(buf, 1, sizeof(buf), file)); - offset += size - ) { - if (options.skip) { - if (zero(buf, size)) { - if (!skip) printf("*\n"); - skip = true; - continue; - } else { - skip = false; - } - } + uint8_t buf[options.cols]; + size_t offset = 0; + for ( + size_t size; + (size = fread(buf, 1, sizeof(buf), file)); + offset += size + ) { + if (options.skip) { + if (zero(buf, size)) { + if (!skip) printf("*\n"); + skip = true; + continue; + } else { + skip = false; + } + } - if (options.offset) { - printf("%08zX: ", offset); - } + if (options.offset) { + printf("%08zX: ", offset); + } - for (size_t i = 0; i < sizeof(buf); ++i) { - if (options.group) { - if (i && !(i % options.group)) { - printf(" "); - } - } - if (i < size) { - printf("%02hhX ", buf[i]); - } else { - printf(" "); - } - } + for (size_t i = 0; i < sizeof(buf); ++i) { + if (options.group) { + if (i && !(i % options.group)) { + printf(" "); + } + } + if (i < size) { + printf("%02hhX ", buf[i]); + } else { + printf(" "); + } + } - if (options.ascii) { - printf(" "); - for (size_t i = 0; i < size; ++i) { - if (options.group) { - if (i && !(i % options.group)) { - printf(" "); - } - } - printf("%c", isprint(buf[i]) ? buf[i] : '.'); - } - } + if (options.ascii) { + printf(" "); + for (size_t i = 0; i < size; ++i) { + if (options.group) { + if (i && !(i % options.group)) { + printf(" "); + } + } + printf("%c", isprint(buf[i]) ? buf[i] : '.'); + } + } - printf("\n"); - } + printf("\n"); + } } static void undump(FILE *file) { - uint8_t byte; - int match; - while (0 < (match = fscanf(file, " %hhx", &byte))) { - printf("%c", byte); - } - if (!match) errx(EX_DATAERR, "invalid input"); + uint8_t byte; + int match; + while (0 < (match = fscanf(file, " %hhx", &byte))) { + printf("%c", byte); + } + if (!match) errx(EX_DATAERR, "invalid input"); } int main(int argc, char *argv[]) { - bool reverse = false; - const char *path = NULL; + bool reverse = false; + const char *path = NULL; - int opt; - while (0 < (opt = getopt(argc, argv, "ac:g:rsz"))) { - switch (opt) { - case 'a': options.ascii ^= true; break; - case 'c': options.cols = strtoul(optarg, NULL, 0); break; - case 'g': options.group = strtoul(optarg, NULL, 0); break; - case 'r': reverse = true; break; - case 's': options.offset ^= true; break; - case 'z': options.skip ^= true; break; - default: return EX_USAGE; - } - } - if (argc > optind) path = argv[optind]; - if (!options.cols) return EX_USAGE; + int opt; + while (0 < (opt = getopt(argc, argv, "ac:g:rsz"))) { + switch (opt) { + case 'a': options.ascii ^= true; break; + case 'c': options.cols = strtoul(optarg, NULL, 0); break; + case 'g': options.group = strtoul(optarg, NULL, 0); break; + case 'r': reverse = true; break; + case 's': options.offset ^= true; break; + case 'z': options.skip ^= true; break; + default: return EX_USAGE; + } + } + if (argc > optind) path = argv[optind]; + if (!options.cols) return EX_USAGE; - FILE *file = path ? fopen(path, "r") : stdin; - if (!file) err(EX_NOINPUT, "%s", path); + FILE *file = path ? fopen(path, "r") : stdin; + if (!file) err(EX_NOINPUT, "%s", path); - if (reverse) { - undump(file); - } else { - dump(file); - } - if (ferror(file)) err(EX_IOERR, "%s", path); + if (reverse) { + undump(file); + } else { + dump(file); + } + if (ferror(file)) err(EX_IOERR, "%s", path); - return EX_OK; + return EX_OK; } |