sbase

suckless unix tools
git clone git://git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

commit d03baf1697443dd71b01aeeb6b7ef5b1ac070cf5
parent c619e168c9be1f7ecf9d4e1bc8f0a594f9ff9b57
Author: FRIGN <dev@frign.de>
Date:   Sun Oct 25 23:26:49 +0100

Add -e and -E flags to od(1) and properly handle endianness

The -e and -E flags allow the user to override the host endianness
and force od(1) to handle input according to a little (-e) or big (-E)
endian environment.
The previous handling was broken as bitshifts alone are already
endian-independent.

Diffstat:
od.1 | 13++++++++++++-
od.c | 35++++++++++++++++++++++-------------
2 files changed, 34 insertions(+), 14 deletions(-)
diff --git a/od.1 b/od.1 @@ -1,4 +1,4 @@ -.Dd 2015-10-09 +.Dd 2015-10-25 .Dt OD 1 .Os sbase .Sh NAME @@ -7,6 +7,7 @@ .Sh SYNOPSIS .Nm .Op Fl A Ar addrformat +.Op Fl E | e .Op Fl t Ar outputformat... .Op Fl v .Op Ar file ... @@ -26,6 +27,12 @@ reads from stdin. is one of d|o|x|n and sets the address to be either in \fId\fRecimal, \fIo\fRctal, he\fIx\fRadecimal or \fIn\fRot printed at all. The default is octal. +.It Fl E | e +Force Little Endian +.Fl ( e ) +or Big Endian +.Fl ( E ) +system-independently. .It Fl t Ar outputformat .Ar outputformat is a list of a|c|d|o|u|x followed by a digit or C|S|I|L and sets @@ -49,3 +56,7 @@ The flag is enabled by default and the 'd' parameter for the .Op Fl t flag is interpreted as 'u'. +.Pp +The +.Op Ee +flags are an extension to that specification. diff --git a/od.c b/od.c @@ -1,5 +1,4 @@ /* See LICENSE file for copyright and license details. */ -#include <endian.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -8,6 +7,8 @@ #include "queue.h" #include "util.h" +#define HOST_BIG_ENDIAN (*(uint16_t *)"\0\xff" == 0xff) + struct type { unsigned char format; unsigned int len; @@ -19,6 +20,7 @@ static unsigned char addr_format = 'o'; static off_t skip = 0; static off_t max = -1; static size_t linelen = 1; +static int big_endian; static void printaddress(off_t addr) @@ -37,7 +39,7 @@ static void printchunk(unsigned char *s, unsigned char format, size_t len) { long long res, basefac; size_t i; - char fmt[] = " %0*ll#"; + char fmt[] = " %#*ll#"; const char *namedict[] = { "nul", "soh", "stx", "etx", "eot", "enq", "ack", @@ -70,17 +72,18 @@ printchunk(unsigned char *s, unsigned char format, size_t len) { } break; default: - res = 0; - basefac = 1; -#if __BYTE_ORDER == __BIG_ENDIAN - for (i = len; i; i--) { - res += s[i - 1] * basefac; -#else - for (i = 0; i < len; i++) { - res += s[i] * basefac; -#endif - basefac <<= 8; + if (big_endian == HOST_BIG_ENDIAN) { + for (res = 0, basefac = 1, i = 0; i < len; i++) { + res += s[i] * basefac; + basefac <<= 8; + } + } else { + for (res = 0, basefac = 1, i = len; i; i--) { + res += s[i - 1] * basefac; + basefac <<= 8; + } } + fmt[2] = big_endian ? '-' : '+'; fmt[6] = format; printf(fmt, (int)(3 * len + len - 1), res); } @@ -165,7 +168,7 @@ lcm(unsigned int a, unsigned int b) static void usage(void) { - eprintf("usage: %s [-A addressformat] [-t outputformat] " + eprintf("usage: %s [-A addressformat] [-E | -e] [-t outputformat] " "[-v] [file ...]\n", argv0); } @@ -177,6 +180,8 @@ main(int argc, char *argv[]) int ret = 0; char *s; + big_endian = HOST_BIG_ENDIAN; + ARGBEGIN { case 'A': s = EARGF(usage()); @@ -184,6 +189,10 @@ main(int argc, char *argv[]) usage(); addr_format = s[0]; break; + case 'E': + case 'e': + big_endian = (ARGC() == 'E'); + break; case 'j': if ((skip = parseoffset(EARGF(usage()))) < 0) usage();