plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

xd.c (7288B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <bio.h>
      4 
      5 unsigned char	odata[16];
      6 unsigned char	data[32];
      7 int		ndata;
      8 int		nread;
      9 unsigned long	addr;
     10 int		repeats;
     11 int		swizzle;
     12 int		swizzle8;
     13 int		flush;
     14 int		abase=2;
     15 int		xd(char *, int);
     16 void		xprint(char *, ...);
     17 void		initarg(void), swizz(void), swizz8(void);
     18 enum{
     19 	Narg=10,
     20 
     21 	TNone=0,
     22 	TAscii,
     23 	TRune,
     24 };
     25 typedef struct Arg Arg;
     26 typedef void fmtfn(char *);
     27 struct Arg
     28 {
     29 	int	chartype;	/* TNone, TAscii, TRunes */
     30 	int	loglen;		/* 0==1, 1==2, 2==4, 3==8 */
     31 	int	base;		/* 0==8, 1==10, 2==16 */
     32 	fmtfn	*fn;		/* function to call with data */
     33 	char	*afmt;		/* format to use to print address */
     34 	char	*fmt;		/* format to use to print data */
     35 }arg[Narg];
     36 int	narg;
     37 
     38 fmtfn	fmt0, fmt1, fmt2, fmt3, fmtc, fmtr;
     39 fmtfn *fmt[4] = {
     40 	fmt0,
     41 	fmt1,
     42 	fmt2,
     43 	fmt3
     44 };
     45 
     46 char *dfmt[4][3] = {
     47 	" %.3uo",	" %.3ud",	" %.2ux",
     48 	" %.6uo",	" %.5ud",	" %.4ux",
     49 	" %.11luo",	" %.10lud",	" %.8lux",
     50 	" %.22lluo",	" %.20llud",	" %.16llux",
     51 };
     52 
     53 char *cfmt[3][3] = {
     54 	"   %c",	"   %c",	"  %c",
     55 	" %.3s",	" %.3s",	" %.2s",
     56 	" %.3uo",	" %.3ud",	" %.2ux",
     57 };
     58 
     59 char *rfmt[1][1] = {
     60 	" %2.2C",
     61 };
     62 
     63 char *afmt[2][3] = {
     64 	"%.7luo ",	"%.7lud ",	"%.7lux ",
     65 	"%7luo ",	"%7lud ",	"%7lux ",
     66 };
     67 
     68 Biobuf	bin;
     69 Biobuf	bout;
     70 
     71 void
     72 main(int argc, char *argv[])
     73 {
     74 	int i, err;
     75 	Arg *ap;
     76 
     77 	Binit(&bout, 1, OWRITE);
     78 	err = 0;
     79 	ap = 0;
     80 	while(argc>1 && argv[1][0]=='-' && argv[1][1]){
     81 		--argc;
     82 		argv++;
     83 		argv[0]++;
     84 		if(argv[0][0] == 'r'){
     85 			repeats = 1;
     86 			if(argv[0][1])
     87 				goto Usage;
     88 			continue;
     89 		}
     90 		if(argv[0][0] == 's'){
     91 			swizzle = 1;
     92 			if(argv[0][1])
     93 				goto Usage;
     94 			continue;
     95 		}
     96 		if(argv[0][0] == 'S'){
     97 			swizzle8 = 1;
     98 			if(argv[0][1])
     99 				goto Usage;
    100 			continue;
    101 		}
    102 		if(argv[0][0] == 'u'){
    103 			flush = 1;
    104 			if(argv[0][1])
    105 				goto Usage;
    106 			continue;
    107 		}
    108 		if(argv[0][0] == 'a'){
    109 			argv[0]++;
    110 			switch(argv[0][0]){
    111 			case 'o':
    112 				abase = 0;
    113 				break;
    114 			case 'd':
    115 				abase = 1;
    116 				break;
    117 			case 'x':
    118 				abase = 2;
    119 				break;
    120 			default:
    121 				goto Usage;
    122 			}
    123 			if(argv[0][1])
    124 				goto Usage;
    125 			continue;
    126 		}
    127 		ap = &arg[narg];
    128 		initarg();
    129 		while(argv[0][0]){
    130 			switch(argv[0][0]){
    131 			case 'c':
    132 				ap->chartype = TAscii;
    133 				ap->loglen = 0;
    134 				if(argv[0][1] || argv[0][-1]!='-')
    135 					goto Usage;
    136 				break;
    137 			case 'R':
    138 				ap->chartype = TRune;
    139 				ap->loglen = 0;
    140 				if(argv[0][1] || argv[0][-1]!='-')
    141 					goto Usage;
    142 				break;
    143 			case 'o':
    144 				ap->base = 0;
    145 				break;
    146 			case 'd':
    147 				ap->base = 1;
    148 				break;
    149 			case 'x':
    150 				ap->base = 2;
    151 				break;
    152 			case 'b':
    153 			case '1':
    154 				ap->loglen = 0;
    155 				break;
    156 			case 'w':
    157 			case '2':
    158 				ap->loglen = 1;
    159 				break;
    160 			case 'l':
    161 			case '4':
    162 				ap->loglen = 2;
    163 				break;
    164 			case 'v':
    165 			case '8':
    166 				ap->loglen = 3;
    167 				break;
    168 			default:
    169 			Usage:
    170    fprint(2, "usage: xd [-u] [-r] [-s] [-a{odx}] [-c|{b1w2l4v8}{odx}] ... file ...\n");
    171 				exits("usage");
    172 			}
    173 			argv[0]++;
    174 		}
    175 		if(ap->chartype == TRune)
    176 			ap->fn = fmtr;
    177 		else if(ap->chartype == TAscii)
    178 			ap->fn = fmtc;
    179 		else
    180 			ap->fn = fmt[ap->loglen];
    181 		ap->fmt = dfmt[ap->loglen][ap->base];
    182 		ap->afmt = afmt[ap>arg][abase];
    183 	}
    184 	if(narg == 0)
    185 		initarg();
    186 	if(argc == 1)
    187 		err = xd(0, 0);
    188 	else if(argc == 2)
    189 		err = xd(argv[1], 0);
    190 	else for(i=1; i<argc; i++)
    191 		err |= xd(argv[i], 1);
    192 	exits(err? "error" : 0);
    193 }
    194 
    195 void
    196 initarg(void)
    197 {
    198 	Arg *ap;
    199 
    200 	ap = &arg[narg++];
    201 	if(narg >= Narg){
    202 		fprint(2, "xd: too many formats (max %d)\n", Narg);
    203 		exits("usage");
    204 	}
    205 	ap->chartype = TNone;
    206 	ap->loglen = 2;
    207 	ap->base = 2;
    208 	ap->fn = fmt2;
    209 	ap->fmt = dfmt[ap->loglen][ap->base];
    210 	ap->afmt = afmt[narg>1][abase];
    211 }
    212 
    213 int
    214 xd(char *name, int title)
    215 {
    216 	int fd;
    217 	int i, star, nsee, nleft;
    218 	Arg *ap;
    219 	Biobuf *bp;
    220 
    221 	fd = 0;
    222 	if(name){
    223 		bp = Bopen(name, OREAD);
    224 		if(bp == 0){
    225 			fprint(2, "xd: can't open %s\n", name);
    226 			return 1;
    227 		}
    228 	}else{
    229 		bp = &bin;
    230 		Binit(bp, fd, OREAD);
    231 	}
    232 	if(title)
    233 		xprint("%s\n", (long)name);
    234 	addr = 0;
    235 	star = 0;
    236 	nsee = 16;
    237 	nleft = 0;
    238 	/* read 32 but see only 16 so that runes are happy */
    239 	while((ndata=Bread(bp, data + nleft, 32 - nleft)) >= 0){
    240 		ndata += nleft;
    241 		nleft = 0;
    242 		nread = ndata;
    243 		if(ndata>nsee)
    244 			ndata = nsee;
    245 		else if(ndata<nsee)
    246 			for(i=ndata; i<nsee; i++)
    247 				data[i] = 0;
    248 		if(swizzle)
    249 			swizz();
    250 		if(swizzle8)
    251 			swizz8();
    252 		if(ndata==nsee && repeats){
    253 			if(addr>0 && data[0]==odata[0]){
    254 				for(i=1; i<nsee; i++)
    255 					if(data[i] != odata[i])
    256 						break;
    257 				if(i == nsee){
    258 					addr += nsee;
    259 					if(star == 0){
    260 						star++;
    261 						xprint("*\n", 0);
    262 					}
    263 					continue;
    264 				}
    265 			}
    266 			for(i=0; i<nsee; i++)
    267 				odata[i] = data[i];
    268 			star = 0;
    269 		}
    270 		for(ap=arg; ap<&arg[narg]; ap++){
    271 			xprint(ap->afmt, addr);
    272 			(*ap->fn)(ap->fmt);
    273 			xprint("\n", 0);
    274 			if(flush)
    275 				Bflush(&bout);
    276 		}
    277 		addr += ndata;
    278 		if(ndata<nsee){
    279 			xprint(afmt[0][abase], addr);
    280 			xprint("\n", 0);
    281 			if(flush)
    282 				Bflush(&bout);
    283 			break;
    284 		}
    285 		if(nread>nsee){
    286 			nleft = nread - nsee;
    287 			memmove(data, data + nsee, nleft);
    288 		}
    289 	}
    290 	Bterm(bp);
    291 	return 0;
    292 }
    293 
    294 void
    295 swizz(void)
    296 {
    297 	uchar *p, *q;
    298 	int i;
    299 	uchar swdata[16];
    300 
    301 	p = data;
    302 	q = swdata;
    303 	for(i=0; i<16; i++)
    304 		*q++ = *p++;
    305 	p = data;
    306 	q = swdata;
    307 	for(i=0; i<4; i++){
    308 		p[0] = q[3];
    309 		p[1] = q[2];
    310 		p[2] = q[1];
    311 		p[3] = q[0];
    312 		p += 4;
    313 		q += 4;
    314 	}
    315 }
    316 
    317 void
    318 swizz8(void)
    319 {
    320 	uchar *p, *q;
    321 	int i;
    322 	uchar swdata[16];
    323 
    324 	p = data;
    325 	q = swdata;
    326 	for(i=0; i<16; i++)
    327 		*q++ = *p++;
    328 	p = data;
    329 	q = swdata;
    330 	for(i=0; i<2; i++){
    331 		p[0] = q[7];
    332 		p[1] = q[6];
    333 		p[2] = q[5];
    334 		p[3] = q[4];
    335 		p[4] = q[3];
    336 		p[5] = q[2];
    337 		p[6] = q[1];
    338 		p[7] = q[0];
    339 		p += 8;
    340 		q += 8;
    341 	}
    342 }
    343 
    344 void
    345 fmt0(char *f)
    346 {
    347 	int i;
    348 	for(i=0; i<ndata; i++)
    349 		xprint(f, data[i]);
    350 }
    351 
    352 void
    353 fmt1(char *f)
    354 {
    355 	int i;
    356 	for(i=0; i<ndata; i+=2)
    357 		xprint(f, (data[i]<<8)|data[i+1]);
    358 }
    359 
    360 void
    361 fmt2(char *f)
    362 {
    363 	int i;
    364 	for(i=0; i<ndata; i+=4)
    365 		xprint(f, (u32int)((data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3]));
    366 }
    367 
    368 void
    369 fmt3(char *f)
    370 {
    371 	int i;
    372 	unsigned long long v;
    373 	for(i=0; i<ndata; i+=8){
    374 		v = (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3];
    375 		v <<= 32;
    376 		v |= (data[i+4]<<24)|(data[i+1+4]<<16)|(data[i+2+4]<<8)|data[i+3+4];
    377 		if(Bprint(&bout, f, v)<0){
    378 			fprint(2, "xd: i/o error\n");
    379 			exits("i/o error");
    380 		}
    381 	}
    382 }
    383 
    384 void
    385 onefmtc(uchar c)
    386 {
    387 	switch(c){
    388 	case '\t':
    389 		xprint(cfmt[1][2], (long)"\\t");
    390 		break;
    391 	case '\r':
    392 		xprint(cfmt[1][2], (long)"\\r");
    393 		break;
    394 	case '\n':
    395 		xprint(cfmt[1][2], (long)"\\n");
    396 		break;
    397 	case '\b':
    398 		xprint(cfmt[1][2], (long)"\\b");
    399 		break;
    400 	default:
    401 		if(c>=0x7F || ' '>c)
    402 			xprint(cfmt[2][2], c);
    403 		else
    404 			xprint(cfmt[0][2], c);
    405 		break;
    406 	}
    407 }
    408 
    409 void
    410 fmtc(char *f)
    411 {
    412 	int i;
    413 
    414 	USED(f);
    415 	for(i=0; i<ndata; i++)
    416 		onefmtc(data[i]);
    417 }
    418 
    419 void
    420 fmtr(char *f)
    421 {
    422 	int i, w, cw;
    423 	Rune r;
    424 	static int nstart;
    425 
    426 	USED(f);
    427 	if(nstart)
    428 		xprint("%*c", 3*nstart, ' ');
    429 	for(i=nstart; i<ndata; )
    430 		if(data[i] < Runeself)
    431 			onefmtc(data[i++]);
    432 		else{
    433 			w = chartorune(&r, (char *)data+i);
    434 			if(w == 1 || i + w>nread)
    435 				onefmtc(data[i++]);
    436 			else{
    437 				cw = w;
    438 				if(i + w>ndata)
    439 					cw = ndata - i;
    440 				xprint(rfmt[0][0], r);
    441 				xprint("%*c", 3*cw-3, ' ');
    442 				i += w;
    443 			}
    444 		}
    445 	if(i > ndata)
    446 		nstart = i - ndata;
    447 	else
    448 		nstart = 0;
    449 }
    450 
    451 void
    452 xprint(char *fmt, ...)
    453 {
    454 	va_list arglist;
    455 
    456 	va_start(arglist, fmt);
    457 	if(Bvprint(&bout, fmt, arglist)<0){
    458 		fprint(2, "xd: i/o error\n");
    459 		exits("i/o error");
    460 	}
    461 	va_end(arglist);
    462 }