File:  [MW Coherent from dump] / coherent / d / bin / od.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * Octal dump.
 * The name is a bit of a joke on a
 * machine that uses hexadecimal,
 * but it will stay like this for now.
 * Defaults to hex unless on the PDP11.
 */

#include <stdio.h>
#include <sys/mdata.h>

#ifndef PDP11
#define	DEFBASE		16
#define	DEFC		'x'
#else
#define	DEFBASE		8
#define	DEFC		'o'
#endif

#define	WIDTH		80
#define	getbyte()	getc(ifp)
#define	getword()	getw(ifp)

/* Forward. */
long	getoffs();
void	mkfmt();
int	putasc();
void	usage();
int	val();

/* Globals. */
int	base = DEFBASE;
char	buf[BUFSIZ];
FILE	*ifp;

main(argc, argv) int argc; char *argv[];
{
	register char *p;
	register c, i;
	long offs;
	int bump, fc, mol, nof, nol, pw;
	char afmt[10], pfmt[10];
	int found;

	found = 0;
	i = 1;
	fc = DEFC;
	if (i<argc && argv[i][0]=='-') {
		p = &argv[i++][1];
		while ((c = *p++) != 0) {
			switch (c) {

			case 'b':
			case 'c':
			case 'd':
			case 'o':
			case 'x':
				if (found)
					usage();
				fc = c;
				found++;
				break;

			default:
				usage();
			}
		}
	}
	setbuf(stdout, buf);
	ifp = stdin;
	nof = 0;
	if (i < argc) {
		++nof;
		if (*(p=argv[i++]) != '+') {
			nof = 0;
			if ((ifp=fopen(p, "rb")) == NULL) {
				fprintf(stderr, "%s: cannot open.\n", p);
				exit(1);
			}
			if (i<argc && argv[i][0]=='+') {
				++i;
				++nof;
			}
		}
	}
	if (nof && i>=argc)
		usage();
	offs = 0;
	if (i < argc) {
		offs = getoffs(argv[i]);
		fseek(ifp, offs, 0);
	}
	if (fc=='b' || fc=='c') {
		bump = sizeof(char);
		if (DEFC == 'o')
			pw = (NBCHAR+2) / 3; else
			pw = (NBCHAR+3) / 4;
	} else {
		bump = sizeof(int);
		if (fc != 'x')
			pw = (NBINT+2) / 3; else
			pw = (NBINT+3) / 4;
	}
	mkfmt(pfmt, pw, fc);
	if (DEFC == 'o')
		mkfmt(afmt, (NBLONG+2)/3, 'O');
	else
		mkfmt(afmt, (NBLONG+3)/4, 'X');
	for (mol=1; mol < (WIDTH-(NBLONG+2)/3)/(pw+1); mol<<=1)
		;
	mol >>= 1;
	nol = 0;
	for (;;) {
		c = (bump==sizeof(char)) ? getbyte() : getword();
		if (ferror(ifp) && c != EOF)	/* partial read */
			clearerr(ifp);		/* treated as good */
		else if (feof(ifp))
			break;
		if (nol >= mol) {
			putchar('\n');
			nol = 0;
		}
		if (nol == 0)
			printf(afmt, offs);
		if (fc!='c' || !putasc(c))
			printf(pfmt, c);
		++nol;
		offs += bump;
	}
	if (nol != 0)
		putchar('\n');
	exit(0);
}

/*
 * Parse the offset at p (form [0[x]]dd*[.][b]) and return its value.
 * Much ado about little.
 */
long
getoffs(p) register char *p;
{
	register char *ep;
	int bflag;
	long offs;

	ep = &p[strlen(p) - 1];		/* pointer to last char of arg */
	bflag = (*ep == 'b');		/* trailing b means blocks */
	if (bflag)
		*ep-- = '\0';
	if (*ep == '.') {		/* trailing . means decimal */
		*ep = '\0';
		base = 10;
	} else if (*p == '0') {
		if (*++p == 'x') {	/* leading 0x means hex */
			++p;
			base = 16;
		} else			/* leading 0 means octal */
			base = 8;
	}
	for (offs = 0; *p != '\0'; offs = base * offs + val(*p++))
		;
	return (bflag) ? offs * BUFSIZ : offs;
}

void
mkfmt(p, w, c) register char *p; register int w, c;
{
	if (c >= 'a')
		*p++ = ' ';
	*p++ = '%';
	if (c != 'd')
		*p++ = '0';
	if (w >= 10) {
		*p++ = '1';
		w -= 10;
	}
	*p++ = w+'0';
	if (c=='b' || c=='c')
		c = DEFC;
	if (c >= 'A' && c <= 'Z') {
		*p++ = 'l';
		c += 'a' - 'A';
	}
	*p++ = c;
	*p = 0;
}

int
putasc(c) register int c;
{
	register n;

	if (c>=' ' && c<='~') {
		putchar(' ');
		putchar(c);
		if (DEFC == 'o')
			n = (NBCHAR+2)/3 - 1; else
			n = (NBCHAR+3)/4 - 1;
		while (n--)
			putchar(' ');
		return (1);
	}
	switch (c) {

	case '\0':
		c = '0';
		break;

	case '\b':
		c = 'b';
		break;

	case '\f':
		c = 'f';
		break;

	case '\n':
		c = 'n';
		break;

	case '\r':
		c = 'r';
		break;

	case '\t':
		c = 't';
		break;

	default:
		return (0);
	}
	putchar(' ');
	putchar('\\');
	putchar(c);
	if (DEFC == 'o')
		n = (NBCHAR+2)/3 - 2; else
		n = (NBCHAR+3)/4 - 2;
	while (n--)
		putchar(' ');
	return (1);
}

void
usage()
{
	fprintf(stderr, "Usage: od [-bcdox] [file] [ [+] offset[.][b] ]\n");
	exit(1);
}

/*
 * Given ASCII character c, return its integer value.
 * Give a usage error if the character is illegal in the given base.
 * Base must be 8, 10 or 16.
 */
int
val(c) register int c;
{
	if (c >= '0' && c <= '7')
		return c - '0';
	else if (base == 8)
		usage();
	else if (c == '8' || c == '9')
		return c - '0';
	else if (base == 10)
		usage();
	else if (c >= 'a' && c <= 'f')
		return c + 10 - 'a';
	else if (c >= 'A' && c <= 'F')
		return c + 10 - 'A';
	else
		usage();
}

/* end of od.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.