aboutsummaryrefslogtreecommitdiff
path: root/toys/posix/od.c
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2013-12-03 15:11:52 -0600
committerRob Landley <rob@landley.net>2013-12-03 15:11:52 -0600
commitb0d4872f532bead29307654bbc511d6083abf2af (patch)
tree06adc223a732480b58b19cb531867b838fc2c88e /toys/posix/od.c
parent83d3a0ba8d98a2d4fcf52d09a3c7f097baf0e1f2 (diff)
downloadtoybox-b0d4872f532bead29307654bbc511d6083abf2af.tar.gz
Redo od whitespace with multiple output types so the columns align.
Factor out single output type into od_out_t(), call it in a loop for each type finding largest output (and if output consumes more than one byte of input average rounding up), pad each output to the largest output times number of bytes input consumed.
Diffstat (limited to 'toys/posix/od.c')
-rw-r--r--toys/posix/od.c179
1 files changed, 99 insertions, 80 deletions
diff --git a/toys/posix/od.c b/toys/posix/od.c
index 01f14b72..6853a9b1 100644
--- a/toys/posix/od.c
+++ b/toys/posix/od.c
@@ -45,12 +45,88 @@ struct odtype {
int size;
};
+static int od_out_t(struct odtype *t, char *buf, int *offset)
+{
+ unsigned k;
+ int throw = 0, pad = 0;
+
+ // Handle ascii
+ if (t->type < 2) {
+ char c = TT.buf[(*offset)++];
+ pad += 4;
+
+ if (!t->type) {
+ c &= 127;
+ if (c<=32) sprintf(buf, "%.3s", ascii+(3*c));
+ else if (c==127) strcpy(buf, "del");
+ else sprintf(buf, "%c", c);
+ } else {
+ char *bfnrtav = "\b\f\n\r\t\a\v", *s = strchr(bfnrtav, c);
+ if (s) sprintf(buf, "\\%c", "bfnrtav0"[s-bfnrtav]);
+ else if (c < 32 || c >= 127) sprintf(buf, "%03o", c);
+ else {
+ // TODO: this should be UTF8 aware.
+ sprintf(buf, "%c", c);
+ }
+ }
+ } else if (CFG_TOYBOX_FLOAT && t->type == 6) {
+ long double ld;
+ union {float f; double d; long double ld;} fdl;
+
+ memcpy(&fdl, TT.buf+*offset, t->size);
+ *offset += t->size;
+ if (sizeof(float) == t->size) {
+ ld = fdl.f;
+ pad += (throw = 8)+7;
+ } else if (sizeof(double) == t->size) {
+ ld = fdl.d;
+ pad += (throw = 17)+8;
+ } else if (sizeof(long double) == t->size) {
+ ld = fdl.ld;
+ pad += (throw = 21)+9;
+ } else error_exit("bad -tf '%d'", t->size);
+
+ sprintf(buf, "%.*Le", throw, ld);
+ // Integer types
+ } else {
+ unsigned long long ll = 0, or;
+ char *c[] = {"%*lld", "%*llu", "%0*llo", "%0*llx"},
+ *class = c[t->type-2];
+
+ // Work out width of field
+ if (t->size == 8) {
+ or = -1LL;
+ if (t->type == 2) or >>= 1;
+ } else or = (1LL<<(8*t->size))-1;
+ throw = sprintf(buf, class, 0, or);
+
+ // Accumulate integer based on size argument
+ for (k=0; k < t->size; k++) {
+ or = TT.buf[(*offset)++];
+ ll |= or << (8*(IS_BIG_ENDIAN ? t->size-k-1 : k));
+ }
+
+ // Handle negative values
+ if (t->type == 2) {
+ or = sizeof(or) - t->size;
+ throw++;
+ if (or && (ll & (1l<<((8*t->size)-1))))
+ ll |= ((or<<(8*or))-1) << (8*t->size);
+ }
+
+ sprintf(buf, class, throw, ll);
+ pad += throw+1;
+ }
+
+ return pad;
+}
+
static void od_outline(void)
{
unsigned flags = toys.optflags;
- char *abases[] = {"", "%07d", "%07o", "%06x"};
- struct odtype *types = (struct odtype *)toybuf, *t;
- int i, len;
+ char buf[128], *abases[] = {"", "%07d", "%07o", "%06x"};
+ struct odtype *types = (struct odtype *)toybuf;
+ int i, j, len, pad;
if (TT.leftover<16) memset(TT.buf+TT.leftover, 0, 16-TT.leftover);
@@ -78,86 +154,27 @@ static void od_outline(void)
TT.leftover = 0;
if (TT.star) return;
+ // Find largest "pad" of the output types.
+ for (i = pad = 0; i<TT.types; i++) {
+ int bytes = 0;
+
+ // If more than one byte of input consumed, average rounding up.
+ j = od_out_t(types+i, buf, &bytes);
+ j = (j+bytes-1)/bytes;
+
+ if (j > pad) pad = j;
+ }
+
// For each output type, print one line
for (i=0; i<TT.types; i++) {
- int j = 0, pad = i ? 8 : 0;
- char buf[128];
-
- t = types+i;
- while (j<len) {
- unsigned k;
- int throw = 0;
-
- // Handle ascii
- if (t->type < 2) {
- char c = TT.buf[j++];
- pad += 4;
-
- if (!t->type) {
- c &= 127;
- if (c<=32) sprintf(buf, "%.3s", ascii+(3*c));
- else if (c==127) strcpy(buf, "del");
- else sprintf(buf, "%c", c);
- } else {
- char *bfnrtav = "\b\f\n\r\t\a\v", *s = strchr(bfnrtav, c);
- if (s) sprintf(buf, "\\%c", "bfnrtav0"[s-bfnrtav]);
- else if (c < 32 || c >= 127) sprintf(buf, "%03o", c);
- else {
- // TODO: this should be UTF8 aware.
- sprintf(buf, "%c", c);
- }
- }
- } else if (CFG_TOYBOX_FLOAT && t->type == 6) {
- long double ld;
- union {float f; double d; long double ld;} fdl;
-
- memcpy(&fdl, TT.buf+j, t->size);
- j += t->size;
- if (sizeof(float) == t->size) {
- ld = fdl.f;
- pad += (throw = 8)+7;
- } else if (sizeof(double) == t->size) {
- ld = fdl.d;
- pad += (throw = 17)+8;
- } else if (sizeof(long double) == t->size) {
- ld = fdl.ld;
- pad += (throw = 21)+9;
- } else error_exit("bad -tf '%d'", t->size);
-
- sprintf(buf, "%.*Le", throw, ld);
- // Integer types
- } else {
- unsigned long long ll = 0, or;
- char *c[] = {"%*lld", "%*llu", "%0*llo", "%0*llx"},
- *class = c[t->type-2];
-
- // Work out width of field
- if (t->size == 8) {
- or = -1LL;
- if (t->type == 2) or >>= 1;
- } else or = (1LL<<(8*t->size))-1;
- throw = sprintf(buf, class, 0, or);
-
- // Accumulate integer based on size argument
- for (k=0; k < t->size; k++) {
- or = TT.buf[j++];
- ll |= or << (8*(IS_BIG_ENDIAN ? t->size-k-1 : k));
- }
-
- // Handle negative values
- if (t->type == 2) {
- or = sizeof(or) - t->size;
- throw++;
- if (or && (ll & (1l<<((8*t->size)-1))))
- ll |= ((or<<(8*or))-1) << (8*t->size);
- }
-
- sprintf(buf, class, throw, ll);
- pad += throw+1;
- }
- xprintf("%*s", pad, buf);
- pad = 0;
+ for (j = 0; j<len;) {
+ int bytes = j;
+
+ // pad for as many bytes as were consumed, and indent non-numbered lines
+ od_out_t(types+i, buf, &bytes);
+ xprintf("%*s", pad*(bytes-j) + 7*(!!i)*!j, buf);
+ j = bytes;
}
xputc('\n');
}
@@ -166,6 +183,7 @@ static void od_outline(void)
TT.buf = (char *)((TT.buf == (char *)TT.bufs) ? TT.bufs+2 : TT.bufs);
}
+// Loop through input files
static void do_od(int fd, char *name)
{
// Skip input, possibly more than one entire file.
@@ -198,6 +216,7 @@ static void do_od(int fd, char *name)
}
}
+// Handle one -t argument (including implicit ones)
static void append_base(char *base)
{
char *s = base;