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