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 swizzle8;
12 int flush;
13 int abase=2;
14 int xd(char *, int);
15 void xprint(char *, ulong);
16 void initarg(void), swizz(void), swizz8(void);
17 enum{
18 Narg=10
19 };
20 typedef struct Arg Arg;
21 typedef void fmtfn(char *);
22 struct Arg
23 {
24 int ascii; /* 0==none, 1==ascii */
25 int loglen; /* 0==1, 1==2, 2==4, 3==8 */
26 int base; /* 0==8, 1==10, 2==16 */
27 fmtfn *fn; /* function to call with data */
28 char *afmt; /* format to use to print address */
29 char *fmt; /* format to use to print data */
30 }arg[Narg];
31 int narg;
33 fmtfn fmt0, fmt1, fmt2, fmt3, fmtc;
34 fmtfn *fmt[4] = {
35 fmt0,
36 fmt1,
37 fmt2,
38 fmt3
39 };
41 char *dfmt[4][3] = {
42 " %.3uo", " %.3ud", " %.2ux",
43 " %.6uo", " %.5ud", " %.4ux",
44 " %.11luo", " %.10lud", " %.8lux",
45 " %.22lluo", " %.20llud", " %.16llux",
46 };
48 char *cfmt[3][3] = {
49 " %c", " %c", " %c",
50 " %.3s", " %.3s", " %.2s",
51 " %.3uo", " %.3ud", " %.2ux",
52 };
54 char *afmt[2][3] = {
55 "%.7luo ", "%.7lud ", "%.7lux ",
56 "%7luo ", "%7lud ", "%7lux ",
57 };
59 Biobuf bin;
60 Biobuf bout;
62 void
63 main(int argc, char *argv[])
64 {
65 int i, err;
66 Arg *ap;
68 Binit(&bout, 1, OWRITE);
69 err = 0;
70 ap = 0;
71 while(argc>1 && argv[1][0]=='-' && argv[1][1]){
72 --argc;
73 argv++;
74 argv[0]++;
75 if(argv[0][0] == 'r'){
76 repeats = 1;
77 if(argv[0][1])
78 goto Usage;
79 continue;
80 }
81 if(argv[0][0] == 's'){
82 swizzle = 1;
83 if(argv[0][1])
84 goto Usage;
85 continue;
86 }
87 if(argv[0][0] == 'S'){
88 swizzle8 = 1;
89 if(argv[0][1])
90 goto Usage;
91 continue;
92 }
93 if(argv[0][0] == 'u'){
94 flush = 1;
95 if(argv[0][1])
96 goto Usage;
97 continue;
98 }
99 if(argv[0][0] == 'a'){
100 argv[0]++;
101 switch(argv[0][0]){
102 case 'o':
103 abase = 0;
104 break;
105 case 'd':
106 abase = 1;
107 break;
108 case 'x':
109 abase = 2;
110 break;
111 default:
112 goto Usage;
114 if(argv[0][1])
115 goto Usage;
116 continue;
118 ap = &arg[narg];
119 initarg();
120 while(argv[0][0]){
121 switch(argv[0][0]){
122 case 'c':
123 ap->ascii = 1;
124 ap->loglen = 0;
125 if(argv[0][1] || argv[0][-1]!='-')
126 goto Usage;
127 break;
128 case 'o':
129 ap->base = 0;
130 break;
131 case 'd':
132 ap->base = 1;
133 break;
134 case 'x':
135 ap->base = 2;
136 break;
137 case 'b':
138 case '1':
139 ap->loglen = 0;
140 break;
141 case 'w':
142 case '2':
143 ap->loglen = 1;
144 break;
145 case 'l':
146 case '4':
147 ap->loglen = 2;
148 break;
149 case 'v':
150 case '8':
151 ap->loglen = 3;
152 break;
153 default:
154 Usage:
155 fprint(2, "usage: xd [-u] [-r] [-s] [-a{odx}] [-c|{b1w2l4v8}{odx}] ... file ...\n");
156 exits("usage");
158 argv[0]++;
160 if(ap->ascii)
161 ap->fn = fmtc;
162 else
163 ap->fn = fmt[ap->loglen];
164 ap->fmt = dfmt[ap->loglen][ap->base];
165 ap->afmt = afmt[ap>arg][abase];
167 if(narg == 0)
168 initarg();
169 if(argc == 1)
170 err = xd(0, 0);
171 else if(argc == 2)
172 err = xd(argv[1], 0);
173 else for(i=1; i<argc; i++)
174 err |= xd(argv[i], 1);
175 exits(err? "error" : 0);
178 void
179 initarg(void)
181 Arg *ap;
183 ap = &arg[narg++];
184 if(narg >= Narg){
185 fprint(2, "xd: too many formats (max %d)\n", Narg);
186 exits("usage");
188 ap->ascii = 0;
189 ap->loglen = 2;
190 ap->base = 2;
191 ap->fn = fmt2;
192 ap->fmt = dfmt[ap->loglen][ap->base];
193 ap->afmt = afmt[narg>1][abase];
196 int
197 xd(char *name, int title)
199 int fd;
200 int i, star;
201 Arg *ap;
202 Biobuf *bp;
204 fd = 0;
205 if(name){
206 bp = Bopen(name, OREAD);
207 if(bp == 0){
208 fprint(2, "xd: can't open %s\n", name);
209 return 1;
211 }else{
212 bp = &bin;
213 Binit(bp, fd, OREAD);
215 if(title)
216 xprint("%s\n", (long)name);
217 addr = 0;
218 star = 0;
219 while((ndata=Bread(bp, data, 16)) >= 0){
220 if(ndata < 16)
221 for(i=ndata; i<16; i++)
222 data[i] = 0;
223 if(swizzle)
224 swizz();
225 if(swizzle8)
226 swizz8();
227 if(ndata==16 && repeats){
228 if(addr>0 && data[0]==odata[0]){
229 for(i=1; i<16; i++)
230 if(data[i] != odata[i])
231 break;
232 if(i == 16){
233 addr += 16;
234 if(star == 0){
235 star++;
236 xprint("*\n", 0);
238 continue;
241 for(i=0; i<16; i++)
242 odata[i] = data[i];
243 star = 0;
245 for(ap=arg; ap<&arg[narg]; ap++){
246 xprint(ap->afmt, addr);
247 (*ap->fn)(ap->fmt);
248 xprint("\n", 0);
249 if(flush)
250 Bflush(&bout);
252 addr += ndata;
253 if(ndata<16){
254 xprint(afmt[0][abase], addr);
255 xprint("\n", 0);
256 if(flush)
257 Bflush(&bout);
258 break;
261 Bterm(bp);
262 return 0;
265 void
266 swizz(void)
268 uchar *p, *q;
269 int i;
270 uchar swdata[16];
272 p = data;
273 q = swdata;
274 for(i=0; i<16; i++)
275 *q++ = *p++;
276 p = data;
277 q = swdata;
278 for(i=0; i<4; i++){
279 p[0] = q[3];
280 p[1] = q[2];
281 p[2] = q[1];
282 p[3] = q[0];
283 p += 4;
284 q += 4;
288 void
289 swizz8(void)
291 uchar *p, *q;
292 int i;
293 uchar swdata[16];
295 p = data;
296 q = swdata;
297 for(i=0; i<16; i++)
298 *q++ = *p++;
299 p = data;
300 q = swdata;
301 for(i=0; i<8; i++){
302 p[0] = q[7];
303 p[1] = q[6];
304 p[2] = q[5];
305 p[3] = q[4];
306 p[4] = q[3];
307 p[5] = q[2];
308 p[6] = q[1];
309 p[7] = q[0];
310 p += 8;
311 q += 8;
315 void
316 fmt0(char *f)
318 int i;
319 for(i=0; i<ndata; i++)
320 xprint(f, data[i]);
323 void
324 fmt1(char *f)
326 int i;
327 for(i=0; i<ndata; i+=2)
328 xprint(f, (data[i]<<8)|data[i+1]);
331 void
332 fmt2(char *f)
334 int i;
335 for(i=0; i<ndata; i+=4)
336 xprint(f, (u32int)((data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3]));
339 void
340 fmt3(char *f)
342 int i;
343 unsigned long long v;
344 for(i=0; i<ndata; i+=8){
345 v = (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3];
346 v <<= 32;
347 v |= (data[i+4]<<24)|(data[i+1+4]<<16)|(data[i+2+4]<<8)|data[i+3+4];
348 if(Bprint(&bout, f, v)<0){
349 fprint(2, "xd: i/o error\n");
350 exits("i/o error");
355 void
356 fmtc(char *f)
358 int i;
360 USED(f);
361 for(i=0; i<ndata; i++)
362 switch(data[i]){
363 case '\t':
364 xprint(cfmt[1][2], (long)"\\t");
365 break;
366 case '\r':
367 xprint(cfmt[1][2], (long)"\\r");
368 break;
369 case '\n':
370 xprint(cfmt[1][2], (long)"\\n");
371 break;
372 case '\b':
373 xprint(cfmt[1][2], (long)"\\b");
374 break;
375 default:
376 if(data[i]>=0x7F || ' '>data[i])
377 xprint(cfmt[2][2], data[i]);
378 else
379 xprint(cfmt[0][2], data[i]);
380 break;
384 void
385 xprint(char *fmt, ulong d)
387 if(Bprint(&bout, fmt, d)<0){
388 fprint(2, "xd: i/o error\n");
389 exits("i/o error");