commit fd0d1e4567c18c7314f2ccc0202b59431318ec31
parent 521c3734af06ce74e9535a542bdae7832c5c595a
Author: Greg Reagle <greg.reagle@umbc.edu>
Date: Mon, 28 Sep 2015 21:02:17 -0400
Created od, with improvements suggested by FRIGN
Diffstat:
M | LICENSE | | | 2 | +- |
M | Makefile | | | 1 | + |
M | README | | | 1 | + |
M | TODO | | | 1 | - |
A | od.1 | | | 30 | ++++++++++++++++++++++++++++++ |
A | od.c | | | 177 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
6 files changed, 210 insertions(+), 2 deletions(-)
diff --git a/LICENSE b/LICENSE
@@ -54,7 +54,7 @@ Authors/contributors include:
© 2014 Ari Malinen <ari.malinen@gmail.com>
© 2014 Brandon Mulcahy <brandon@jangler.info>
© 2014 Adria Garriga <rhaps0dy@installgentoo.com>
-© 2014 Greg Reagle <greg.reagle@umbc.edu>
+© 2014-2015 Greg Reagle <greg.reagle@umbc.edu>
© 2015 Tai Chi Minh Ralph Eastwood <tcmreastwood@gmail.com>
© 2015 Quentin Rameau <quinq@quinq.eu.org>
© 2015 Dionysis Grigoropoulos <info@erethon.com>
diff --git a/Makefile b/Makefile
@@ -115,6 +115,7 @@ BIN =\
nice\
nl\
nohup\
+ od\
paste\
printenv\
printf\
diff --git a/README b/README
@@ -54,6 +54,7 @@ The following tools are implemented:
=*|o nice .
#*|o nl .
=*|o nohup .
+ od a lot
#*|o paste .
=*|x printenv .
#*|o printf .
diff --git a/TODO b/TODO
@@ -10,7 +10,6 @@ diff
ed
getconf
install
-od
patch
pathchk
stty
diff --git a/od.1 b/od.1
@@ -0,0 +1,30 @@
+.Dd September 28, 2015
+.Dt OD 1
+.Os sbase
+.Sh NAME
+.Nm od
+.Nd octal dump
+.Sh SYNOPSIS
+.Nm
+.Op Fl A Ar d|o|x|n
+.Op Fl t Ar a|c|d|o|u|x
+.Op Ar file...
+.Sh DESCRIPTION
+.Nm
+writes an octal dump of each
+.Ar file
+to stdout. If no
+.Ar file
+is given, then
+.Nm
+reads from stdin.
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Fl A Ar d|o|x|n
+Display the address in base \fId\fRecimal | \fIo\fRctal |
+he\fIx\fRadecimal | \fIn\fRone. If unspecified, the default is octal.
+.It Fl t Ar a|c|d|o|u|x
+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.
+.El
diff --git a/od.c b/od.c
@@ -0,0 +1,177 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+static char addr_radix = 'o';
+static char *type = "o";
+
+static void
+usage(void)
+{
+ eprintf("usage: %s [-A d|o|x|n] [-t a|c|d|o|u|x] [file ...]\n", argv0);
+}
+
+static void
+print_address(FILE *f, size_t addr)
+{
+ switch (addr_radix) {
+ 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];
+
+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 {
+ char_string[0] = c;
+ char_string[1] = '\0';
+ return char_string;
+ }
+}
+
+static void
+print_content(FILE *f, char type, unsigned char cont)
+{
+ switch (type) {
+ case 'a':
+ fprintf(f, "%3s ", named_char(cont));
+ break;
+ case 'c':
+ fprintf(f, "%3s ", escaped_char(cont));
+ break;
+ case 'd':
+ fprintf(f, "%4hhd ", cont);
+ break;
+ case 'o':
+ fprintf(f, "%03hho ", cont);
+ break;
+ case 'u':
+ fprintf(f, "%3hhu ", cont);
+ break;
+ case 'x':
+ fprintf(f, "%02hhx ", cont);
+ break;
+ }
+}
+
+static void
+od(FILE *fp_in, const char *name_in, FILE *fp_out, const char *name_out)
+{
+ unsigned char buf[BUFSIZ];
+ size_t addr, buf_size, i;
+ const size_t bytes_per_line = 16;
+
+ addr = 0;
+ for (; (buf_size = fread(buf, 1, BUFSIZ, fp_in)); ) {
+ for (i = 0; i < buf_size; ++i, ++addr) {
+ if ((addr % bytes_per_line) == 0) {
+ if (addr != 0) fprintf(fp_out, "%s", "\n");
+ print_address(fp_out, addr);
+ }
+ print_content(fp_out, type[0], buf[i]);
+ }
+ if (feof(fp_in) || ferror(fp_in) || ferror(fp_out))
+ break;
+ }
+ fprintf(fp_out, "\n%.7zx \n", addr);
+}
+
+int
+main(int argc, char *argv[])
+{
+ FILE *fp;
+ int ret = 0;
+ char *s;
+
+ ARGBEGIN {
+ case 'A':
+ s = EARGF(usage());
+ if (strlen(s) > 1 || !strchr("doxn", s[0]))
+ usage();
+ addr_radix = s[0];
+ break;
+ case 't':
+ type = EARGF(usage());
+ if (strlen(type) > 1 || !strchr("acdoux", type[0]))
+ usage();
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ if (!argc) {
+ od(stdin, "<stdin>", stdout, "<stdout>");
+ } else {
+ for (; *argv; argc--, argv++) {
+ if (!strcmp(*argv, "-")) {
+ *argv = "<stdin>";
+ fp = stdin;
+ } else if (!(fp = fopen(*argv, "r"))) {
+ weprintf("fopen %s:", *argv);
+ ret = 1;
+ continue;
+ }
+ od(fp, *argv, stdout, "<stdout>");
+ if (fp != stdin && fshut(fp, *argv))
+ ret = 1;
+ }
+ }
+
+ ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>");
+
+ return ret;
+}