Blob
1 #include <u.h>2 #include <libc.h>3 #include <bio.h>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,21 TNone=0,22 TAscii,23 TRune,24 };25 typedef struct Arg Arg;26 typedef void fmtfn(char *);27 struct Arg28 {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;38 fmtfn fmt0, fmt1, fmt2, fmt3, fmtc, fmtr;39 fmtfn *fmt[4] = {40 fmt0,41 fmt1,42 fmt2,43 fmt344 };46 char *dfmt[4][3] = {47 " %.3uo", " %.3ud", " %.2ux",48 " %.6uo", " %.5ud", " %.4ux",49 " %.11luo", " %.10lud", " %.8lux",50 " %.22lluo", " %.20llud", " %.16llux",51 };53 char *cfmt[3][3] = {54 " %c", " %c", " %c",55 " %.3s", " %.3s", " %.2s",56 " %.3uo", " %.3ud", " %.2ux",57 };59 char *rfmt[1][1] = {60 " %2.2C",61 };63 char *afmt[2][3] = {64 "%.7luo ", "%.7lud ", "%.7lux ",65 "%7luo ", "%7lud ", "%7lux ",66 };68 Biobuf bin;69 Biobuf bout;71 void72 main(int argc, char *argv[])73 {74 int i, err;75 Arg *ap;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 else180 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 }195 void196 initarg(void)197 {198 Arg *ap;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 }213 int214 xd(char *name, int title)215 {216 int fd;217 int i, star, nsee, nleft;218 Arg *ap;219 Biobuf *bp;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 }294 void295 swizz(void)296 {297 uchar *p, *q;298 int i;299 uchar swdata[16];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 }317 void318 swizz8(void)319 {320 uchar *p, *q;321 int i;322 uchar swdata[16];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<8; 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 }344 void345 fmt0(char *f)346 {347 int i;348 for(i=0; i<ndata; i++)349 xprint(f, data[i]);350 }352 void353 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 }360 void361 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 }368 void369 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 }384 void385 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 else404 xprint(cfmt[0][2], c);405 break;406 }407 }409 void410 fmtc(char *f)411 {412 int i;414 USED(f);415 for(i=0; i<ndata; i++)416 onefmtc(data[i]);417 }419 void420 fmtr(char *f)421 {422 int i, w, cw;423 Rune r;424 static int nstart;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 else448 nstart = 0;449 }451 void452 xprint(char *fmt, ...)453 {454 va_list arglist;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 }