Minix1.5/commands/od.c

Compare this file to the similar file:
Show the results in this format:

/* od - octal dump		   Author: Andy Tanenbaum */

#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>


int bflag, cflag, dflag, oflag, xflag, hflag, linenr, width, state, ever;
int prevwds[8];
long off;
char buf[512], buffer[BUFSIZ];
int next;
int bytespresent;
char hexit();

main(argc, argv)
int argc;
char *argv[];
{
  int k, flags;
  long offset();
  char *p;

  /* Process flags */
  setbuf(stdout, buffer);
  flags = 0;
  p = argv[1];
  if (argc > 1 && *p == '-') {
	/* Flags present. */
	flags++;
	p++;
	while (*p) {
		switch (*p) {
		    case 'b':	bflag++;	break;
		    case 'c':	cflag++;	break;
		    case 'd':	dflag++;	break;
		    case 'h':	hflag++;	break;
		    case 'o':	oflag++;	break;
		    case 'x':	xflag++;	break;
		    default:	usage();
		}
		p++;
	}
  } else {
	oflag = 1;
  }
  if ((bflag | cflag | dflag | oflag | xflag) == 0) oflag = 1;
  k = (flags ? 2 : 1);
  if (bflag | cflag) {
	width = 8;
  } else if (oflag) {
	width = 7;
  } else if (dflag) {
	width = 6;
  } else {
	width = 5;
  }

  /* Process file name, if any. */
  p = argv[k];
  if (k < argc && *p != '+') {
	/* Explicit file name given. */
	close(0);
	if (open(argv[k], O_RDONLY) != 0) {
		std_err("od: cannot open ");
		std_err(argv[k]);
		std_err("\n");
		exit(1);
	}
	k++;
  }

  /* Process offset, if any. */
  if (k < argc) {
	/* Offset present. */
	off = offset(argc, argv, k);
	off = (off / 16L) * 16L;
	lseek(0, off, SEEK_SET);
  }
  dumpfile();
  addrout(off);
  printf("\n");
  exit(0);
}


long offset(argc, argv, k)
int argc;
char *argv[];
int k;
{
  int dot, radix;
  char str[80], *p, c;
  long val;

  /* See if the offset is decimal. */
  dot = 0;
  p = argv[k];
  while (*p)
	if (*p++ == '.') dot = 1;

  /* Convert offset to binary. */
  radix = (dot ? 10 : 8);
  val = 0;
  p = argv[k];
  if (*p == '+') p++;
  while (*p != 0 && *p != '.') {
	c = *p++;
	if (c < '0' || c > '9') {
		printf("Bad character in offset: %c\n", c);
		exit(1);
	}
	val = radix * val + c - '0';
  }

  p = argv[k + 1];
  if (k + 1 == argc - 1 && *p == 'b') val = 512L * val;
  return(val);
}


dumpfile()
{
  int k;
  short *words;

  while ((k = getwords(&words))) {	/* 'k' is # bytes read */
	if (k == 16 && same(words, prevwds) && ever == 1) {
		if (state == 0) {
			printf("*\n");
			state = 1;
			off += 16;
			continue;
		} else if (state == 1) {
			off += 16;
			continue;
		}
	}
	addrout(off);
	off += k;
	state = 0;
	ever = 1;
	linenr = 1;
	if (oflag) wdump(words, k, 8);
	if (dflag) wdump(words, k, 10);
	if (xflag) wdump(words, k, 16);
	if (cflag) bdump(words, k, 'c');
	if (bflag) bdump(words, k, 'b');
	for (k = 0; k < 8; k++) prevwds[k] = words[k];
	for (k = 0; k < 8; k++) words[k] = 0;
  }
}


wdump(words, k, radix)
short *words;
int k, radix;
{
  int i;

  if (linenr++ != 1) printf("       ");
  for (i = 0; i < (k + 1) / 2; i++) outword(words[i], radix);
  printf("\n");
}


bdump(bytes, k, c)
char bytes[16];
int k;
char c;
{
  int i;

  if (linenr++ != 1) printf("       ");
  for (i = 0; i < k; i++) byte(bytes[i] & 0377, c);
  printf("\n");
}

byte(val, c)
int val;
char c;
{
  if (c == 'b') {
	printf(" ");
	outnum(val, 7);
	return;
  }
  if (val == 0)
	printf("  \\0");
  else if (val == '\b')
	printf("  \\b");
  else if (val == '\f')
	printf("  \\f");
  else if (val == '\n')
	printf("  \\n");
  else if (val == '\r')
	printf("  \\r");
  else if (val == '\t')
	printf("  \\t");
  else if (val >= ' ' && val < 0177)
	printf("   %c", val);
  else {
	printf(" ");
	outnum(val, 7);
  }
}


int getwords(words)
short **words;
{
  int count;

  if (next >= bytespresent) {
	bytespresent = read(0, buf, 512);
	next = 0;
  }
  if (next >= bytespresent) return(0);
  *words = (short *) &buf[next];
  if (next + 16 <= bytespresent)
	count = 16;
  else
	count = bytespresent - next;

  next += count;
  return(count);
}

int same(w1, w2)
short *w1;
int *w2;
{
  int i;
  i = 8;
  while (i--)
	if (*w1++ != *w2++) return(0);
  return(1);
}

outword(val, radix)
int val, radix;
{
/* Output 'val' in 'radix' in a field of total size 'width'. */

  int i;

  if (radix == 16) i = width - 4;
  if (radix == 10) i = width - 5;
  if (radix == 8) i = width - 6;
  if (i == 1)
	printf(" ");
  else if (i == 2)
	printf("  ");
  else if (i == 3)
	printf("   ");
  else if (i == 4)
	printf("    ");
  outnum(val, radix);
}


outnum(num, radix)
int num, radix;
{
/* Output a number with all leading 0s present.  Octal is 6 places,
 * decimal is 5 places, hex is 4 places.
 */
  int d, i;
  unsigned val;
  char s[8];

  val = (unsigned) num;
  if (radix == 8)
	d = 6;
  else if (radix == 10)
	d = 5;
  else if (radix == 16)
	d = 4;
  else if (radix == 7) {
	d = 3;
	radix = 8;
  }
  for (i = 0; i < d; i++) {
	s[i] = val % radix;
	val -= s[i];
	val = val / radix;
  }
  for (i = d - 1; i >= 0; i--) {
	if (s[i] > 9)
		printf("%c", 'a' + s[i] - 10);
	else
		printf("%c", s[i] + '0');
  }
}


addrout(l)
long l;
{
  int i;

  if (hflag == 0) {
	for (i = 0; i < 7; i++)
		printf("%c", (int) ((l >> (18 - 3 * i)) & 07) + '0');
  } else {
	for (i = 0; i < 7; i++)
		printf("%c", hexit((int) ((l >> (24 - 4 * i)) & 0x0F)));
  }
}

char hexit(k)
int k;
{
  if (k <= 9)
	return('0' + k);
  else
	return('A' + k - 10);
}

usage()
{
  std_err("Usage: od [-bcdhox] [file] [ [+] offset [.] [b] ]");
}