Blob
1 #include <u.h>2 #include <libc.h>3 #include <bio.h>5 unsigned char odata[16];6 unsigned char data[16];7 int ndata;8 unsigned long addr;9 int repeats;10 int swizzle;11 int flush;12 int abase=2;13 int xd(char *, int);14 void xprint(char *, ulong);15 void initarg(void), swizz(void);16 enum{17 Narg=1018 };19 typedef struct Arg Arg;20 typedef void fmtfn(char *);21 struct Arg22 {23 int ascii; /* 0==none, 1==ascii */24 int loglen; /* 0==1, 1==2, 2==4, 3==8 */25 int base; /* 0==8, 1==10, 2==16 */26 fmtfn *fn; /* function to call with data */27 char *afmt; /* format to use to print address */28 char *fmt; /* format to use to print data */29 }arg[Narg];30 int narg;32 fmtfn fmt0, fmt1, fmt2, fmt3, fmtc;33 fmtfn *fmt[4] = {34 fmt0,35 fmt1,36 fmt2,37 fmt338 };40 char *dfmt[4][3] = {41 " %.3uo", " %.3ud", " %.2ux",42 " %.6uo", " %.5ud", " %.4ux",43 " %.11luo", " %.10lud", " %.8lux",44 " %.22lluo", " %.20llud", " %.16llux",45 };47 char *cfmt[3][3] = {48 " %c", " %c", " %c",49 " %.3s", " %.3s", " %.2s",50 " %.3uo", " %.3ud", " %.2ux",51 };53 char *afmt[2][3] = {54 "%.7luo ", "%.7lud ", "%.7lux ",55 "%7luo ", "%7lud ", "%7lux ",56 };58 Biobuf bin;59 Biobuf bout;61 void62 main(int argc, char *argv[])63 {64 int i, err;65 Arg *ap;67 Binit(&bout, 1, OWRITE);68 err = 0;69 ap = 0;70 while(argc>1 && argv[1][0]=='-' && argv[1][1]){71 --argc;72 argv++;73 argv[0]++;74 if(argv[0][0] == 'r'){75 repeats = 1;76 if(argv[0][1])77 goto Usage;78 continue;79 }80 if(argv[0][0] == 's'){81 swizzle = 1;82 if(argv[0][1])83 goto Usage;84 continue;85 }86 if(argv[0][0] == 'u'){87 flush = 1;88 if(argv[0][1])89 goto Usage;90 continue;91 }92 if(argv[0][0] == 'a'){93 argv[0]++;94 switch(argv[0][0]){95 case 'o':96 abase = 0;97 break;98 case 'd':99 abase = 1;100 break;101 case 'x':102 abase = 2;103 break;104 default:105 goto Usage;106 }107 if(argv[0][1])108 goto Usage;109 continue;110 }111 ap = &arg[narg];112 initarg();113 while(argv[0][0]){114 switch(argv[0][0]){115 case 'c':116 ap->ascii = 1;117 ap->loglen = 0;118 if(argv[0][1] || argv[0][-1]!='-')119 goto Usage;120 break;121 case 'o':122 ap->base = 0;123 break;124 case 'd':125 ap->base = 1;126 break;127 case 'x':128 ap->base = 2;129 break;130 case 'b':131 case '1':132 ap->loglen = 0;133 break;134 case 'w':135 case '2':136 ap->loglen = 1;137 break;138 case 'l':139 case '4':140 ap->loglen = 2;141 break;142 case 'v':143 case '8':144 ap->loglen = 3;145 break;146 default:147 Usage:148 fprint(2, "usage: xd [-u] [-r] [-s] [-a{odx}] [-c|{b1w2l4v8}{odx}] ... file ...\n");149 exits("usage");150 }151 argv[0]++;152 }153 if(ap->ascii)154 ap->fn = fmtc;155 else156 ap->fn = fmt[ap->loglen];157 ap->fmt = dfmt[ap->loglen][ap->base];158 ap->afmt = afmt[ap>arg][abase];159 }160 if(narg == 0)161 initarg();162 if(argc == 1)163 err = xd(0, 0);164 else if(argc == 2)165 err = xd(argv[1], 0);166 else for(i=1; i<argc; i++)167 err |= xd(argv[i], 1);168 exits(err? "error" : 0);169 }171 void172 initarg(void)173 {174 Arg *ap;176 ap = &arg[narg++];177 if(narg >= Narg){178 fprint(2, "xd: too many formats (max %d)\n", Narg);179 exits("usage");180 }181 ap->ascii = 0;182 ap->loglen = 2;183 ap->base = 2;184 ap->fn = fmt2;185 ap->fmt = dfmt[ap->loglen][ap->base];186 ap->afmt = afmt[narg>1][abase];187 }189 int190 xd(char *name, int title)191 {192 int fd;193 int i, star;194 Arg *ap;195 Biobuf *bp;197 fd = 0;198 if(name){199 bp = Bopen(name, OREAD);200 if(bp == 0){201 fprint(2, "xd: can't open %s\n", name);202 return 1;203 }204 }else{205 bp = &bin;206 Binit(bp, fd, OREAD);207 }208 if(title)209 xprint("%s\n", (long)name);210 addr = 0;211 star = 0;212 while((ndata=Bread(bp, data, 16)) >= 0){213 if(ndata < 16)214 for(i=ndata; i<16; i++)215 data[i] = 0;216 if(swizzle)217 swizz();218 if(ndata==16 && repeats){219 if(addr>0 && data[0]==odata[0]){220 for(i=1; i<16; i++)221 if(data[i] != odata[i])222 break;223 if(i == 16){224 addr += 16;225 if(star == 0){226 star++;227 xprint("*\n", 0);228 }229 continue;230 }231 }232 for(i=0; i<16; i++)233 odata[i] = data[i];234 star = 0;235 }236 for(ap=arg; ap<&arg[narg]; ap++){237 xprint(ap->afmt, addr);238 (*ap->fn)(ap->fmt);239 xprint("\n", 0);240 if(flush)241 Bflush(&bout);242 }243 addr += ndata;244 if(ndata<16){245 xprint(afmt[0][abase], addr);246 xprint("\n", 0);247 if(flush)248 Bflush(&bout);249 break;250 }251 }252 Bterm(bp);253 return 0;254 }256 void257 swizz(void)258 {259 uchar *p, *q;260 int i;261 uchar swdata[16];263 p = data;264 q = swdata;265 for(i=0; i<16; i++)266 *q++ = *p++;267 p = data;268 q = swdata;269 for(i=0; i<4; i++){270 p[0] = q[3];271 p[1] = q[2];272 p[2] = q[1];273 p[3] = q[0];274 p += 4;275 q += 4;276 }277 }279 void280 fmt0(char *f)281 {282 int i;283 for(i=0; i<ndata; i++)284 xprint(f, data[i]);285 }287 void288 fmt1(char *f)289 {290 int i;291 for(i=0; i<ndata; i+=sizeof(unsigned short))292 xprint(f, (data[i]<<8)|data[i+1]);293 }295 void296 fmt2(char *f)297 {298 int i;299 for(i=0; i<ndata; i+=sizeof(unsigned long))300 xprint(f, (u32int)((data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3]));301 }303 void304 fmt3(char *f)305 {306 int i;307 unsigned long long v;308 for(i=0; i<ndata; i+=sizeof(unsigned long long)){309 v = (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3];310 v <<= 32;311 v |= (data[i+4]<<24)|(data[i+1+4]<<16)|(data[i+2+4]<<8)|data[i+3+4];312 if(Bprint(&bout, f, v)<0){313 fprint(2, "xd: i/o error\n");314 exits("i/o error");315 }316 }317 }319 void320 fmtc(char *f)321 {322 int i;324 USED(f);325 for(i=0; i<ndata; i++)326 switch(data[i]){327 case '\t':328 xprint(cfmt[1][2], (long)"\\t");329 break;330 case '\r':331 xprint(cfmt[1][2], (long)"\\r");332 break;333 case '\n':334 xprint(cfmt[1][2], (long)"\\n");335 break;336 case '\b':337 xprint(cfmt[1][2], (long)"\\b");338 break;339 default:340 if(data[i]>=0x7F || ' '>data[i])341 xprint(cfmt[2][2], data[i]);342 else343 xprint(cfmt[0][2], data[i]);344 break;345 }346 }348 void349 xprint(char *fmt, ulong d)350 {351 if(Bprint(&bout, fmt, d)<0){352 fprint(2, "xd: i/o error\n");353 exits("i/o error");354 }355 }