[PATCH] od: added support for different size values

From: Greg Reagle <greg.reagle_AT_umbc.edu>
Date: Thu, 1 Oct 2015 14:07:23 -0400

---
 od.1 |   3 ++
 od.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++-------------------
 2 files changed, 82 insertions(+), 30 deletions(-)
diff --git a/od.1 b/od.1
index 6fe99c8..b47d752 100644
--- a/od.1
+++ b/od.1
_AT_@ -30,6 +30,9 @@ he\fIx\fRadecimal | \fIn\fRone.  If unspecified, the default is octal.
 Display the content as n\fIa\fRmed character, \fIc\fRharacter, signed
 \fId\fRecimal, \fIo\fRctal, \fIu\fRnsigned decimal, or
 he\fIx\fRadecimal.  If unspecified, the default is octal.
+Another character is optional indicating size of \fIC\fRhar, \fII\fRnt,
+\fIS\fRhort, or \fIL\fRong.  If unspecified the default is short, or
+char for types a or c.
 .It Fl v
 Always set. Write all input data, including duplicate lines.
 .It Fl j Ar skip
diff --git a/od.c b/od.c
index eab7f9e..1ab1ea3 100644
--- a/od.c
+++ b/od.c
_AT_@ -11,6 +11,7 @@ static off_t maxbytes = -1;
 static off_t skip = 0;
 static unsigned char addrbase = 'o';
 static unsigned char type = 'o';
+static unsigned char size = 'S';
 
 static void
 printaddress(FILE *f, off_t addr)
_AT_@ -26,7 +27,7 @@ printaddress(FILE *f, off_t addr)
 }
 
 static void
-printchar(FILE *f, unsigned char c)
+printvalue(FILE *f, unsigned char *c)
 {
 	const char *namedict[] = {
 		"nul", "soh", "stx", "etx", "eot", "enq", "ack",
_AT_@ -41,55 +42,95 @@ printchar(FILE *f, unsigned char c)
 		['\n'] = "\\n", ['\v'] = "\\v",
 		['\f'] = "\\f", ['\r'] = "\\r",
 	};
-	const char *fmtdict[] = {
-		['d'] = "%4hhd ", ['o'] = "%03hho ",
-		['u'] = "%3hhu ", ['x'] = "%02hhx ",
+	const char *fmtdict[][130] = {
+		['d']['C'] = "%4hhd ", ['o']['C'] = "%03hho ",
+		['u']['C'] = "%3hhu ", ['x']['C'] = "%02hhx ",
+		['d']['S'] = "%6hd ",  ['o']['S'] = "%06ho ",
+		['u']['S'] = "%5hu ",  ['x']['S'] = "%04hx ",
+		['d']['I'] = "%11d ",  ['o']['I'] = "%011o ",
+		['u']['I'] = "%10u ",  ['x']['I'] = "%08x ",
+		['d']['L'] = "%20ld ", ['o']['L'] = "%022lo ",
+		['u']['L'] = "%20lu ", ['x']['L'] = "%016lx ",
 	};
 
 	switch (type) {
 	case 'a':
-		c &= ~128; /* clear high bit as required by standard */
-		if (c < LEN(namedict) || c == 127) {
-			fprintf(f, "%3s ", (c == 127) ? "del" : namedict[c]);
+		*c &= ~128; /* clear high bit as required by standard */
+		if (*c < LEN(namedict) || *c == 127) {
+			fprintf(f, "%3s ", (*c == 127) ? "del" : namedict[*c]);
 		} else {
-			fprintf(f, "%3c ", c);
+			fprintf(f, "%3c ", *c);
 		}
 		break;
 	case 'c':
-		if (strchr("\a\b\t\n\b\f\r\0", c)) {
-			fprintf(f, "%3s ", escdict[c]);
+		if (strchr("\a\b\t\n\v\b\f\r\0", *c)) {
+			fprintf(f, "%3s ", escdict[*c]);
 		} else {
-			fprintf(f, "%3c ", c);
+			fprintf(f, "%3c ", *c);
 		}
 		break;
 	default:
-		fprintf(f, fmtdict[type], c);
+		switch (size) {
+		case 'C':
+			fprintf(f, fmtdict[type][size], *c);
+			break;
+		case 'I':
+			fprintf(f, fmtdict[type][size], * (int *) c);
+			break;
+		case 'L':
+			fprintf(f, fmtdict[type][size], * (long *) c);
+			break;
+		case 'S':
+		default:
+			fprintf(f, fmtdict[type][size], * (short *) c);
+			break;
+		}
 	}
 }
 
 static void
+clear(unsigned char * buffer, int size)
+{
+	for (int i = 0; i < size; ++i)
+		buffer[i] = 0;
+}
+
+static void
 od(FILE *in, char *in_name, FILE *out, char *out_name)
 {
-	off_t addr;
-	size_t i, chunklen;
-	unsigned char buf[BUFSIZ];
+	off_t addr, counter;
+	size_t chunklen, incr;
+	unsigned char buf[1], value[sizeof(long)];
+	const int sizedict[] = {
+		['C'] = sizeof(char), ['I'] = sizeof(int), ['L'] = sizeof(long),
+		['S'] = sizeof(short),
+	};
 
-	for (addr = 0; (chunklen = fread(buf, 1, BUFSIZ, in)); ) {
-		for (i = 0; i < chunklen && (maxbytes == -1 ||
-		     (addr - skip) < maxbytes); ++i, ++addr) {
-			if (addr - skip < 0)
-				continue;
-			if (((addr - skip) % bytes_per_line) == 0) {
-				if (addr - skip)
-					fputc('\n', out);
-				printaddress(out, addr);
-			}
-			printchar(out, buf[i]);
+	incr = sizedict[size];
+	for (addr = 0; (addr < skip) && (chunklen = fread(buf, 1, 1, in)); ++addr)
+		if (feof(in) || ferror(in))
+			break;
+	clear(value, incr);
+	counter = addr - skip;
+	for ( ; ((maxbytes == -1 || (counter < maxbytes)) && 
+		 (chunklen = fread(buf, 1, 1, in))); ++addr, ++counter) {
+		if ((counter % bytes_per_line) == 0) {
+			if (counter)
+				fputc('\n', out);
+			printaddress(out, addr);
+		}
+		value[counter % incr] = buf[0];
+		if ( ((counter % incr) == (incr - 1)) && counter) {
+			printvalue(out, value);
+			clear(value, incr);
 		}
-		if (feof(in) || ferror(in) || ferror(out))
+		if (ferror(in) || ferror(out))
 			break;
 	}
-	if (addr - skip > 0)
+	if ((counter > 0) && (counter % incr) > 0) {
+		printvalue(out, value);
+	}
+	if (counter > 0)
 		fputc('\n', out);
 	if (addrbase != 'n') {
 		printaddress(out, MAX(addr, skip));
_AT_@ -127,10 +168,18 @@ main(int argc, char *argv[])
 		break;
 	case 't':
 		s = EARGF(usage());
-		if (strlen(s) != 1 || !strchr("acdoux", s[0]))
+		if (strlen(s) < 1 || strlen(s) > 2 || !strchr("acdoux", s[0]))
 			usage();
 		type = s[0];
-		break;
+		if (strlen(s) == 2) {
+			if (!strchr("doux", s[0]) || !strchr("CISL", s[1])) {
+				usage();
+			} else {
+				size = s[1];
+			}
+		}
+		if (type == 'a' || type == 'c')
+			size = 'C';
 	case 'v':
 		/* Always set. Use "uniq -f 1 -c" to handle duplicate lines. */
 		break;
-- 
1.9.1
--------------090204040209020607000307--
Received on Mon Sep 17 2001 - 00:00:00 CEST

This archive was generated by hypermail 2.3.0 : Fri Oct 02 2015 - 00:36:10 CEST