123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- /* vim: tabstop=4 shiftwidth=4 noexpandtab
- * This file is part of ToaruOS and is released under the terms
- * of the NCSA / University of Illinois License - see LICENSE.md
- * Copyright (C) 2018 K. Lange
- *
- * hexify - Convert binary to hex.
- *
- * This is based on the output of xxd.
- * Does NOT a hex-to-bin option - something to consider.
- */
- #include <stdio.h>
- #include <ctype.h>
- #include <errno.h>
- #include <unistd.h>
- #include <string.h>
- void print_line(unsigned char * buf, unsigned int width, unsigned int sizer, unsigned int offset) {
- fprintf(stdout, "%08x: ", sizer);
- for (unsigned int i = 0; i < width; ) {
- if (i >= offset) {
- fprintf(stdout, " ");
- } else {
- fprintf(stdout, "%02x", buf[i]);
- }
- i++;
- if (i == width) break; /* in case of odd width */
- if (i >= offset) {
- fprintf(stdout, " ");
- } else {
- fprintf(stdout, "%02x ", buf[i]);
- }
- i++;
- }
- fprintf(stdout, " ");
- for (unsigned int i = 0; i < width; i++) {
- if (i >= offset) {
- fprintf(stdout, " ");
- } else {
- if (isprint(buf[i])) {
- fprintf(stdout, "%c", buf[i]);
- } else {
- fprintf(stdout, ".");
- }
- }
- }
- fprintf(stdout, "\n");
- }
- static int stoih(int w, char c[w], unsigned int *out) {
- *out = 0;
- for (int i = 0; i < w; ++i) {
- (*out) <<= 4;
- if (c[i] >= '0' && c[i] <= '9') {
- *out |= (c[i] - '0');
- } else if (c[i] >= 'A' && c[i] <= 'F') {
- *out |= (c[i] - 'A' + 0xA);
- } else if (c[i] >= 'a' && c[i] <= 'f') {
- *out |= (c[i] - 'a' + 0xA);
- } else {
- *out = 0;
- return 1;
- }
- }
- return 0;
- }
- int main(int argc, char * argv[]) {
- unsigned int width = 16; /* TODO make configurable */
- int opt;
- int direction = 0;
- while ((opt = getopt(argc, argv, "?w:d")) != -1) {
- switch (opt) {
- default:
- case '?':
- fprintf(stderr, "%s: convert to/from hexadecimal dump\n", argv[0]);
- return 1;
- case 'w':
- width = atoi(optarg);
- break;
- case 'd':
- direction = 1;
- break;
- }
- }
- FILE * f;
- char * name;
- if (optind < argc) {
- f = fopen(argv[optind], "r");
- name = argv[optind];
- if (!f) {
- fprintf(stderr, "%s: %s: %s\n", argv[0], argv[optind], strerror(errno));
- }
- } else {
- name = "[stdin]";
- f = stdin;
- }
- if (direction == 0) {
- /* Convert to hexadecimal */
- unsigned int sizer = 0;
- unsigned int offset = 0;
- unsigned char buf[width];
- while (!feof(f)) {
- unsigned int r = fread(buf+offset, 1, width-offset, f);
- offset += r;
- if (offset == width) {
- print_line(buf, width, sizer, offset);
- offset = 0;
- sizer += width;
- }
- }
- if (offset != 0) {
- print_line(buf, width, sizer, offset);
- }
- } else {
- /* Convert from hexify's output format */
- unsigned int eoffset = 0;
- unsigned int lineno = 1;
- while (!feof(f)) {
- /* Read offset */
- char offset_bytes[8];
- fread(&offset_bytes, 1, 8, f);
- /* Convert offset for verification */
- unsigned int offset;
- if (stoih(8, offset_bytes, &offset)) {
- fprintf(stderr, "%s: %s: syntax error (bad offset) on line %d\n", argv[0], name, lineno);
- fprintf(stderr, "offset bytes: %8s\n", offset_bytes);
- return 1;
- }
- if (offset != eoffset) {
- fprintf(stderr, "%s: %s: offset mismatch on line %d\n", argv[0], name, lineno);
- fprintf(stderr, "expected 0x%x, got 0x%x\n", offset, eoffset);
- return 1;
- }
- /* Read ": " */
- char tmp[2];
- fread(&tmp, 1, 2, f);
- if (tmp[0] != ':' || tmp[1] != ' ') {
- fprintf(stderr, "%s: %s: syntax error (unexpected characters after offset) on line %d\n", argv[0], name, lineno);
- return 1;
- }
- /* Read [width] characters */
- for (unsigned int i = 0; i < width; ) {
- unsigned int byte = 0;
- for (unsigned int j = 0; i < width && j < 2; ++j, ++i) {
- fread(&tmp, 1, 2, f);
- if (tmp[0] == ' ' && tmp[1] == ' ') {
- /* done; return */
- return 0;
- }
- if (stoih(2, tmp, &byte)) {
- fprintf(stderr, "%s: %s: syntax error (bad byte) on line %d\n", argv[0], name, lineno);
- fprintf(stderr, "byte bytes: %2s\n", tmp);
- return 1;
- }
- fwrite(&byte, 1, 1, stdout);
- }
- /* Read space */
- fread(&tmp, 1, 1, f);
- if (tmp[0] != ' ') {
- fprintf(stderr, "%s: %s: syntax error (unexpected characters after byte) on line %d\n", argv[0], name, lineno);
- fprintf(stderr, "unexpected character: %c\n", tmp[0]);
- return 1;
- }
- }
- fread(&tmp, 1, 1, f);
- if (tmp[0] != ' ') {
- fprintf(stderr, "%s: %s: syntax error (unexpected characters after bytes) on line %d\n", argv[0], name, lineno);
- }
- /* Read correct number of characters, plus line feed */
- char tmp2[width+2];
- fread(&tmp2, 1, width+1, f);
- tmp2[width+1] = '\0';
- if (tmp2[width] != '\n') {
- fprintf(stderr, "%s: %s: syntax error: expected end of line, got garbage on line %d\n", argv[0], name, lineno);
- fprintf(stderr, "eol data: %s\n", tmp2);
- }
- lineno++;
- eoffset += width;
- }
- }
- return 0;
- }
|