Refactor parts of od(1)
It was possible to make some sections of the code shorter. Also fix a bug where the last printed address was always in hex rather than depending on the radix chosen.
This commit is contained in:
parent
fd0d1e4567
commit
d49bce7fc8
170
od.c
170
od.c
|
@ -4,8 +4,9 @@
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static char addr_radix = 'o';
|
static size_t bytes_per_line = 16;
|
||||||
static char *type = "o";
|
static unsigned char radix = 'o';
|
||||||
|
static unsigned char type = 'o';
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
|
@ -14,120 +15,87 @@ usage(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_address(FILE *f, size_t addr)
|
printaddress(FILE *f, size_t addr)
|
||||||
{
|
{
|
||||||
switch (addr_radix) {
|
char fmt[] = "%06z# ";
|
||||||
case 'x':
|
|
||||||
fprintf(f, "%06zx ", addr);
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
fprintf(f, "%06zd ", addr);
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
fprintf(f, "%s", " ");
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
default:
|
|
||||||
fprintf(f, "%06zo ", addr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static char char_string[2];
|
if (radix == 'n') {
|
||||||
|
fputc(' ', f);
|
||||||
static const char *
|
|
||||||
escaped_char(unsigned char c)
|
|
||||||
{
|
|
||||||
switch (c) {
|
|
||||||
case '\0':
|
|
||||||
return "\\0";
|
|
||||||
case '\a':
|
|
||||||
return "\\a";
|
|
||||||
case '\b':
|
|
||||||
return "\\b";
|
|
||||||
case '\t':
|
|
||||||
return "\\t";
|
|
||||||
case '\n':
|
|
||||||
return "\\n";
|
|
||||||
case '\v':
|
|
||||||
return "\\v";
|
|
||||||
case '\f':
|
|
||||||
return "\\f";
|
|
||||||
case '\r':
|
|
||||||
return "\\r";
|
|
||||||
default:
|
|
||||||
char_string[0] = c;
|
|
||||||
char_string[1] = '\0';
|
|
||||||
return char_string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
named_char(unsigned char c)
|
|
||||||
{
|
|
||||||
static const int table_size = 33;
|
|
||||||
static const char * named_chars[] = {"nul", "soh", "stx", "etx", "eot",
|
|
||||||
"enq", "ack", "bel", "bs", "ht", "nl", "vt", "ff", "cr", "so", "si",
|
|
||||||
"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb", "can", "em",
|
|
||||||
"sub", "esc", "fs", "gs", "rs", "us", "sp"};
|
|
||||||
|
|
||||||
c &= ~128; /* clear high bit of byte, as required by standard */
|
|
||||||
if (c < table_size) {
|
|
||||||
return named_chars[c];
|
|
||||||
} else if (c == 127) {
|
|
||||||
return "del";
|
|
||||||
} else {
|
} else {
|
||||||
char_string[0] = c;
|
fmt[4] = radix;
|
||||||
char_string[1] = '\0';
|
fprintf(f, fmt, addr);
|
||||||
return char_string;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_content(FILE *f, char type, unsigned char cont)
|
printchar(FILE *f, unsigned char c)
|
||||||
{
|
{
|
||||||
switch (type) {
|
const char *namedict[] = {
|
||||||
case 'a':
|
"nul", "soh", "stx", "etx", "eot", "enq", "ack",
|
||||||
fprintf(f, "%3s ", named_char(cont));
|
"bel", "bs", "ht", "nl", "vt", "ff", "cr",
|
||||||
break;
|
"so", "si", "dle", "dc1", "dc2", "dc3", "dc4",
|
||||||
case 'c':
|
"nak", "syn", "etb", "can", "em", "sub", "esc",
|
||||||
fprintf(f, "%3s ", escaped_char(cont));
|
"fs", "gs", "rs", "us", "sp",
|
||||||
break;
|
[127] = "del"
|
||||||
case 'd':
|
};
|
||||||
fprintf(f, "%4hhd ", cont);
|
const char *escdict[] = {
|
||||||
break;
|
['\0'] = "\\0", ['\a'] = "\\a",
|
||||||
case 'o':
|
['\b'] = "\\b", ['\t'] = "\\t",
|
||||||
fprintf(f, "%03hho ", cont);
|
['\n'] = "\\n", ['\v'] = "\\v",
|
||||||
break;
|
['\f'] = "\\f", ['\r'] = "\\r",
|
||||||
case 'u':
|
};
|
||||||
fprintf(f, "%3hhu ", cont);
|
const char *fmtdict[] = {
|
||||||
break;
|
['d'] = "%4hhd ", ['o'] = "%03hho ",
|
||||||
case 'x':
|
['u'] = "%3hhu ", ['x'] = "%02hhx ",
|
||||||
fprintf(f, "%02hhx ", cont);
|
};
|
||||||
break;
|
|
||||||
|
if (type != 'a' && type != 'c') {
|
||||||
|
fprintf(f, fmtdict[type], c);
|
||||||
|
} else {
|
||||||
|
switch (type) {
|
||||||
|
case 'a':
|
||||||
|
c &= ~128; /* clear high bit as required by standard */
|
||||||
|
if (c < LEN(namedict) || c == 127) {
|
||||||
|
fprintf(f, "%3s ", namedict[c]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
if (strchr("\a\b\t\n\b\f\r\0", c)) {
|
||||||
|
fprintf(f, "%3s ", escdict[c]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fprintf(f, "%3c ", c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
od(FILE *fp_in, const char *name_in, FILE *fp_out, const char *name_out)
|
od(FILE *in, char *in_name, FILE *out, char *out_name)
|
||||||
{
|
{
|
||||||
unsigned char buf[BUFSIZ];
|
unsigned char buf[BUFSIZ];
|
||||||
size_t addr, buf_size, i;
|
char fmt[] = "\n%.6z#";
|
||||||
const size_t bytes_per_line = 16;
|
off_t addr, bread, i;
|
||||||
|
|
||||||
addr = 0;
|
addr = 0;
|
||||||
for (; (buf_size = fread(buf, 1, BUFSIZ, fp_in)); ) {
|
for (; (bread = fread(buf, 1, BUFSIZ, in)); ) {
|
||||||
for (i = 0; i < buf_size; ++i, ++addr) {
|
for (i = 0; i < bread; ++i, ++addr) {
|
||||||
if ((addr % bytes_per_line) == 0) {
|
if ((addr % bytes_per_line) == 0) {
|
||||||
if (addr != 0) fprintf(fp_out, "%s", "\n");
|
if (addr)
|
||||||
print_address(fp_out, addr);
|
fputc('\n', out);
|
||||||
|
printaddress(out, addr);
|
||||||
}
|
}
|
||||||
print_content(fp_out, type[0], buf[i]);
|
printchar(out, buf[i]);
|
||||||
}
|
}
|
||||||
if (feof(fp_in) || ferror(fp_in) || ferror(fp_out))
|
if (feof(in) || ferror(in) || ferror(out))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fprintf(fp_out, "\n%.7zx \n", addr);
|
if (radix != 'n') {
|
||||||
|
fmt[5] = radix;
|
||||||
|
fprintf(out, fmt, addr);
|
||||||
|
}
|
||||||
|
fputc('\n', out);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -135,19 +103,20 @@ main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
ARGBEGIN {
|
ARGBEGIN {
|
||||||
case 'A':
|
case 'A':
|
||||||
s = EARGF(usage());
|
s = EARGF(usage());
|
||||||
if (strlen(s) > 1 || !strchr("doxn", s[0]))
|
if (strlen(s) > 1 || !strchr("doxn", s[0]))
|
||||||
usage();
|
usage();
|
||||||
addr_radix = s[0];
|
radix = s[0];
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
type = EARGF(usage());
|
s = EARGF(usage());
|
||||||
if (strlen(type) > 1 || !strchr("acdoux", type[0]))
|
if (strlen(s) > 1 || !strchr("acdoux", s[0]))
|
||||||
usage();
|
usage();
|
||||||
|
type = s[0];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
|
@ -171,7 +140,8 @@ main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
|
ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>") |
|
||||||
|
fshut(stderr, "<stderr>");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user