427 lines · 6.6 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h> uchar		odata[16];uchar		data[32];int		ndata;int		nread;ulong		addr;int		repeats;int		swizzle;int		flush;int		abase=2;int		xd(char *, int);void		xprint(char *, ...);void		initarg(void), swizz(void);enum{	Narg=10, 	TNone=0,	TAscii,	TRune,};typedef struct Arg Arg;typedef void fmtfn(char *);struct Arg{	int	chartype;		/* TNone, TAscii, TRunes */	int	loglen;		/* 0==1, 1==2, 2==4, 3==8 */	int	base;		/* 0==8, 1==10, 2==16 */	fmtfn	*fn;		/* function to call with data */	char	*afmt;		/* format to use to print address */	char	*fmt;		/* format to use to print data */}arg[Narg];int	narg; fmtfn	fmt0, fmt1, fmt2, fmt3, fmtc, fmtr;fmtfn *fmt[4] = {	fmt0,	fmt1,	fmt2,	fmt3}; char *dfmt[4][3] = {	" %.3uo",	" %.3ud",	" %.2ux",	" %.6uo",	" %.5ud",	" %.4ux",	" %.11luo",	" %.10lud",	" %.8lux",	" %.22lluo",	" %.20llud",	" %.16llux",}; char *cfmt[3][3] = {	"   %c",	"   %c", 	"  %c",	" %.3s",	" %.3s",	" %.2s",	" %.3uo",	" %.3ud",	" %.2ux",}; char *rfmt[1][1] = {	" %2.2C",}; char *afmt[2][3] = {	"%.7luo ",	"%.7lud ",	"%.7lux ",	"%7luo ",	"%7lud ",	"%7lux ",}; Biobuf	bin;Biobuf	bout; voidmain(int argc, char *argv[]){	int i, err;	Arg *ap; 	Binit(&bout, 1, OWRITE);	err = 0;	ap = 0;	while(argc>1 && argv[1][0]=='-' && argv[1][1]){		--argc;		argv++;		argv[0]++;		if(argv[0][0] == 'r'){			repeats = 1;			if(argv[0][1])				goto Usage;			continue;		}		if(argv[0][0] == 's'){			swizzle = 1;			if(argv[0][1])				goto Usage;			continue;		}		if(argv[0][0] == 'u'){			flush = 1;			if(argv[0][1])				goto Usage;			continue;		}		if(argv[0][0] == 'a'){			argv[0]++;			switch(argv[0][0]){			case 'o':				abase = 0;				break;			case 'd':				abase = 1;				break;			case 'x':				abase = 2;				break;			default:				goto Usage;			}			if(argv[0][1])				goto Usage;			continue;		}		ap = &arg[narg];		initarg();		while(argv[0][0]){			switch(argv[0][0]){			case 'c':				ap->chartype = TAscii;				ap->loglen = 0;				if(argv[0][1] || argv[0][-1]!='-')					goto Usage;				break;			case 'R':				ap->chartype = TRune;				ap->loglen = 0;				if(argv[0][1] || argv[0][-1]!='-')					goto Usage;				break;			case 'o':				ap->base = 0;				break;			case 'd':				ap->base = 1;				break;			case 'x':				ap->base = 2;				break;			case 'b':			case '1':				ap->loglen = 0;				break;			case 'w':			case '2':				ap->loglen = 1;				break;			case 'l':			case '4':				ap->loglen = 2;				break;			case 'v':			case '8':				ap->loglen = 3;				break;			default:			Usage:   fprint(2, "usage: xd [-u] [-r] [-s] [-a{odx}] [-c|{b1w2l4v8}{odx}] ... file ...\n");				exits("usage");			}			argv[0]++;		}		if(ap->chartype == TRune)			ap->fn = fmtr;		else if(ap->chartype == TAscii)			ap->fn = fmtc;		else			ap->fn = fmt[ap->loglen];		ap->fmt = dfmt[ap->loglen][ap->base];		ap->afmt = afmt[ap>arg][abase];	}	if(narg == 0)		initarg();	if(argc == 1)		err = xd(0, 0);	else if(argc == 2)		err = xd(argv[1], 0);	else for(i=1; i<argc; i++)		err |= xd(argv[i], 1);	exits(err? "error" : 0);} voidinitarg(void){	Arg *ap; 	ap = &arg[narg++];	if(narg >= Narg){		fprint(2, "xd: too many formats (max %d)\n", Narg);		exits("usage");	}	ap->chartype = TNone;	ap->loglen = 2;	ap->base = 2;	ap->fn = fmt2;	ap->fmt = dfmt[ap->loglen][ap->base];	ap->afmt = afmt[narg>1][abase];} intxd(char *name, int title){	int fd;	int i, star, nsee, nleft;	Arg *ap;	Biobuf *bp; 	fd = 0;	if(name){		bp = Bopen(name, OREAD);		if(bp == 0){			fprint(2, "xd: can't open %s\n", name);			return 1;		}	}else{		bp = &bin;		Binit(bp, fd, OREAD);	}	if(title)		xprint("%s\n", name);	addr = 0;	star = 0;	nsee = 16;	nleft = 0;	/* read 32 but see only 16 so that runes are happy */	while((ndata=Bread(bp, data + nleft, 32 - nleft)) >= 0){		ndata += nleft;		nleft = 0;		nread = ndata;		if(ndata>nsee)			ndata = nsee;		else if(ndata<nsee)			for(i=ndata; i<nsee; i++)				data[i] = 0;		if(swizzle)			swizz();		if(ndata==nsee && repeats){			if(addr>0 && data[0]==odata[0]){				for(i=1; i<nsee; i++)					if(data[i] != odata[i])						break;				if(i == nsee){					addr += nsee;					if(star == 0){						star++;						xprint("*\n", 0);					}					continue;				}			}			for(i=0; i<nsee; i++)				odata[i] = data[i];			star = 0;		}		for(ap=arg; ap<&arg[narg]; ap++){			xprint(ap->afmt, addr);			(*ap->fn)(ap->fmt);			xprint("\n", 0);			if(flush)				Bflush(&bout);		}		addr += ndata;		if(ndata<nsee){			xprint(afmt[0][abase], addr);			xprint("\n", 0);			if(flush)				Bflush(&bout);			break;		}		if(nread>nsee){			nleft = nread - nsee;			memmove(data, data + nsee, nleft);		}	}	Bterm(bp);	return 0;} voidswizz(void){	uchar *p, *q;	int i;	uchar swdata[16]; 	p = data;	q = swdata;	for(i=0; i<16; i++)		*q++ = *p++;	p = data;	q = swdata;	for(i=0; i<4; i++){		p[0] = q[3];		p[1] = q[2];		p[2] = q[1];		p[3] = q[0];		p += 4;		q += 4;	}} voidfmt0(char *f){	int i;	for(i=0; i<ndata; i++)		xprint(f, data[i]);} voidfmt1(char *f){	int i;	for(i=0; i<ndata; i+=sizeof(ushort))		xprint(f, (data[i]<<8)|data[i+1]);} voidfmt2(char *f){	int i;	for(i=0; i<ndata; i+=sizeof(ulong))		xprint(f, (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3]);} voidfmt3(char *f){	int i;	uvlong v; 	for(i=0; i<ndata; i+=sizeof(uvlong)){		v = (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3];		v <<= 32;		v |= (data[i+4]<<24)|(data[i+1+4]<<16)|(data[i+2+4]<<8)|data[i+3+4];		if(Bprint(&bout, f, v)<0){			fprint(2, "xd: i/o error\n");			exits("i/o error");		}	}} voidonefmtc(uchar c){	switch(c){	case '\t':		xprint(cfmt[1][2], "\\t");		break;	case '\r':		xprint(cfmt[1][2], "\\r");		break;	case '\n':		xprint(cfmt[1][2], "\\n");		break;	case '\b':		xprint(cfmt[1][2], "\\b");		break;	default:		if(c>=0x7F || ' '>c)			xprint(cfmt[2][2], c);		else			xprint(cfmt[0][2], c);		break;	}} voidfmtc(char *f){	int i; 	USED(f);	for(i=0; i<ndata; i++)		onefmtc(data[i]);} voidfmtr(char *f){	int i, w, cw;	Rune r;	static int nstart; 	USED(f);	if(nstart)			xprint("%*c", 3*nstart, ' ');	for(i=nstart; i<ndata; )		if(data[i] < Runeself)			onefmtc(data[i++]);		else{			w = chartorune(&r, (char *)data+i);			if(w == 1 || i + w>nread)				onefmtc(data[i++]);			else{				cw = w;				if(i + w>ndata)					cw = ndata - i;				xprint(rfmt[0][0], r);					xprint("%*c", 3*cw-3, ' ');				i += w;			}		}	if(i > ndata)		nstart = i - ndata;	else		nstart = 0;} voidxprint(char *fmt, ...){	va_list arglist; 	va_start(arglist, fmt);	if(Bvprint(&bout, fmt, arglist)<0){		fprint(2, "xd: i/o error\n");		exits("i/o error");	}	va_end(arglist);}