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 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;
32 fmtfn fmt0, fmt1, fmt2, fmt3, fmtc;
33 fmtfn *fmt[4] = {
34 fmt0,
35 fmt1,
36 fmt2,
37 fmt3
38 };
40 char *dfmt[4][3] = {
41 " %.3uo", " %.3ud", " %.2ux",
42 " %.6uo", " %.5ud", " %.4ux",
43 " %.11luo", " %.10lud", " %.8lux",
44 " %.22lluo", " %.20llud", " %.16llux",
45 };
47 char *cfmt[3][3] = {
48 " %c", " %c", " %c",
49 " %.3s", " %.3s", " %.2s",
50 " %.3uo", " %.3ud", " %.2ux",
51 };
53 char *afmt[2][3] = {
54 "%.7luo ", "%.7lud ", "%.7lux ",
55 "%7luo ", "%7lud ", "%7lux ",
56 };
58 Biobuf bin;
59 Biobuf bout;
61 void
62 main(int argc, char *argv[])
63 {
64 int i, err;
65 Arg *ap;
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;
107 if(argv[0][1])
108 goto Usage;
109 continue;
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");
151 argv[0]++;
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];
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);
171 void
172 initarg(void)
174 Arg *ap;
176 ap = &arg[narg++];
177 if(narg >= Narg){
178 fprint(2, "xd: too many formats (max %d)\n", Narg);
179 exits("usage");
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];
189 int
190 xd(char *name, int title)
192 int fd;
193 int i, star;
194 Arg *ap;
195 Biobuf *bp;
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;
204 }else{
205 bp = &bin;
206 Binit(bp, fd, OREAD);
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);
229 continue;
232 for(i=0; i<16; i++)
233 odata[i] = data[i];
234 star = 0;
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);
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;
252 Bterm(bp);
253 return 0;
256 void
257 swizz(void)
259 uchar *p, *q;
260 int i;
261 uchar swdata[16];
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;
279 void
280 fmt0(char *f)
282 int i;
283 for(i=0; i<ndata; i++)
284 xprint(f, data[i]);
287 void
288 fmt1(char *f)
290 int i;
291 for(i=0; i<ndata; i+=sizeof(unsigned short))
292 xprint(f, (data[i]<<8)|data[i+1]);
295 void
296 fmt2(char *f)
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]);
303 void
304 fmt3(char *f)
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");
319 void
320 fmtc(char *f)
322 int i;
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;
348 void
349 xprint(char *fmt, long d)
351 if(Bprint(&bout, fmt, d)<0){
352 fprint(2, "xd: i/o error\n");
353 exits("i/o error");