1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 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 *, long); 15 void initarg(void), swizz(void); 16 enum{ 17 Narg=10 18 }; 19 typedef struct Arg Arg; 20 typedef void fmtfn(char *); 21 struct Arg 22 { 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; 31 32 fmtfn fmt0, fmt1, fmt2, fmt3, fmtc; 33 fmtfn *fmt[4] = { 34 fmt0, 35 fmt1, 36 fmt2, 37 fmt3 38 }; 39 40 char *dfmt[4][3] = { 41 " %.3uo", " %.3ud", " %.2ux", 42 " %.6uo", " %.5ud", " %.4ux", 43 " %.11luo", " %.10lud", " %.8lux", 44 " %.22lluo", " %.20llud", " %.16llux", 45 }; 46 47 char *cfmt[3][3] = { 48 " %c", " %c", " %c", 49 " %.3s", " %.3s", " %.2s", 50 " %.3uo", " %.3ud", " %.2ux", 51 }; 52 53 char *afmt[2][3] = { 54 "%.7luo ", "%.7lud ", "%.7lux ", 55 "%7luo ", "%7lud ", "%7lux ", 56 }; 57 58 Biobuf bin; 59 Biobuf bout; 60 61 void 62 main(int argc, char *argv[]) 63 { 64 int i, err; 65 Arg *ap; 66 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 else 156 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 } 170 171 void 172 initarg(void) 173 { 174 Arg *ap; 175 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 } 188 189 int 190 xd(char *name, int title) 191 { 192 int fd; 193 int i, star; 194 Arg *ap; 195 Biobuf *bp; 196 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 } 255 256 void 257 swizz(void) 258 { 259 uchar *p, *q; 260 int i; 261 uchar swdata[16]; 262 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 } 278 279 void 280 fmt0(char *f) 281 { 282 int i; 283 for(i=0; i<ndata; i++) 284 xprint(f, data[i]); 285 } 286 287 void 288 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 } 294 295 void 296 fmt2(char *f) 297 { 298 int i; 299 for(i=0; i<ndata; i+=sizeof(unsigned long)) 300 xprint(f, (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3]); 301 } 302 303 void 304 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 } 318 319 void 320 fmtc(char *f) 321 { 322 int i; 323 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 else 343 xprint(cfmt[0][2], data[i]); 344 break; 345 } 346 } 347 348 void 349 xprint(char *fmt, long d) 350 { 351 if(Bprint(&bout, fmt, d)<0){ 352 fprint(2, "xd: i/o error\n"); 353 exits("i/o error"); 354 } 355 } 356