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 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;
38 fmtfn fmt0, fmt1, fmt2, fmt3, fmtc, fmtr;
39 fmtfn *fmt[4] = {
40 fmt0,
41 fmt1,
42 fmt2,
43 fmt3
44 };
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 void
72 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;
102 if(argv[0][0] == 'u'){
103 flush = 1;
104 if(argv[0][1])
105 goto Usage;
106 continue;
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;
123 if(argv[0][1])
124 goto Usage;
125 continue;
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");
173 argv[0]++;
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];
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);
195 void
196 initarg(void)
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");
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];
213 int
214 xd(char *name, int title)
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;
228 }else{
229 bp = &bin;
230 Binit(bp, fd, OREAD);
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);
263 continue;
266 for(i=0; i<nsee; i++)
267 odata[i] = data[i];
268 star = 0;
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);
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;
285 if(nread>nsee){
286 nleft = nread - nsee;
287 memmove(data, data + nsee, nleft);
290 Bterm(bp);
291 return 0;
294 void
295 swizz(void)
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;
317 void
318 swizz8(void)
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<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;
344 void
345 fmt0(char *f)
347 int i;
348 for(i=0; i<ndata; i++)
349 xprint(f, data[i]);
352 void
353 fmt1(char *f)
355 int i;
356 for(i=0; i<ndata; i+=2)
357 xprint(f, (data[i]<<8)|data[i+1]);
360 void
361 fmt2(char *f)
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]));
368 void
369 fmt3(char *f)
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");
384 void
385 onefmtc(uchar c)
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;
409 void
410 fmtc(char *f)
412 int i;
414 USED(f);
415 for(i=0; i<ndata; i++)
416 onefmtc(data[i]);
419 void
420 fmtr(char *f)
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;
445 if(i > ndata)
446 nstart = i - ndata;
447 else
448 nstart = 0;
451 void
452 xprint(char *fmt, ...)
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");
461 va_end(arglist);