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 }