Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
 
5
uchar		odata[16];
6
uchar		data[32];
7
int		ndata;
8
int		nread;
9
ulong		addr;
10
int		repeats;
11
int		swizzle;
12
int		flush;
13
int		abase=2;
14
int		xd(char *, int);
15
void		xprint(char *, ...);
16
void		initarg(void), swizz(void);
17
enum{
18
	Narg=10,
19
 
20
	TNone=0,
21
	TAscii,
22
	TRune,
23
};
24
typedef struct Arg Arg;
25
typedef void fmtfn(char *);
26
struct Arg
27
{
28
	int	chartype;		/* TNone, TAscii, TRunes */
29
	int	loglen;		/* 0==1, 1==2, 2==4, 3==8 */
30
	int	base;		/* 0==8, 1==10, 2==16 */
31
	fmtfn	*fn;		/* function to call with data */
32
	char	*afmt;		/* format to use to print address */
33
	char	*fmt;		/* format to use to print data */
34
}arg[Narg];
35
int	narg;
36
 
37
fmtfn	fmt0, fmt1, fmt2, fmt3, fmtc, fmtr;
38
fmtfn *fmt[4] = {
39
	fmt0,
40
	fmt1,
41
	fmt2,
42
	fmt3
43
};
44
 
45
char *dfmt[4][3] = {
46
	" %.3uo",	" %.3ud",	" %.2ux",
47
	" %.6uo",	" %.5ud",	" %.4ux",
48
	" %.11luo",	" %.10lud",	" %.8lux",
49
	" %.22lluo",	" %.20llud",	" %.16llux",
50
};
51
 
52
char *cfmt[3][3] = {
53
	"   %c",	"   %c", 	"  %c",
54
	" %.3s",	" %.3s",	" %.2s",
55
	" %.3uo",	" %.3ud",	" %.2ux",
56
};
57
 
58
char *rfmt[1][1] = {
59
	" %2.2C",
60
};
61
 
62
char *afmt[2][3] = {
63
	"%.7luo ",	"%.7lud ",	"%.7lux ",
64
	"%7luo ",	"%7lud ",	"%7lux ",
65
};
66
 
67
Biobuf	bin;
68
Biobuf	bout;
69
 
70
void
71
main(int argc, char *argv[])
72
{
73
	int i, err;
74
	Arg *ap;
75
 
76
	Binit(&bout, 1, OWRITE);
77
	err = 0;
78
	ap = 0;
79
	while(argc>1 && argv[1][0]=='-' && argv[1][1]){
80
		--argc;
81
		argv++;
82
		argv[0]++;
83
		if(argv[0][0] == 'r'){
84
			repeats = 1;
85
			if(argv[0][1])
86
				goto Usage;
87
			continue;
88
		}
89
		if(argv[0][0] == 's'){
90
			swizzle = 1;
91
			if(argv[0][1])
92
				goto Usage;
93
			continue;
94
		}
95
		if(argv[0][0] == 'u'){
96
			flush = 1;
97
			if(argv[0][1])
98
				goto Usage;
99
			continue;
100
		}
101
		if(argv[0][0] == 'a'){
102
			argv[0]++;
103
			switch(argv[0][0]){
104
			case 'o':
105
				abase = 0;
106
				break;
107
			case 'd':
108
				abase = 1;
109
				break;
110
			case 'x':
111
				abase = 2;
112
				break;
113
			default:
114
				goto Usage;
115
			}
116
			if(argv[0][1])
117
				goto Usage;
118
			continue;
119
		}
120
		ap = &arg[narg];
121
		initarg();
122
		while(argv[0][0]){
123
			switch(argv[0][0]){
124
			case 'c':
125
				ap->chartype = TAscii;
126
				ap->loglen = 0;
127
				if(argv[0][1] || argv[0][-1]!='-')
128
					goto Usage;
129
				break;
130
			case 'R':
131
				ap->chartype = TRune;
132
				ap->loglen = 0;
133
				if(argv[0][1] || argv[0][-1]!='-')
134
					goto Usage;
135
				break;
136
			case 'o':
137
				ap->base = 0;
138
				break;
139
			case 'd':
140
				ap->base = 1;
141
				break;
142
			case 'x':
143
				ap->base = 2;
144
				break;
145
			case 'b':
146
			case '1':
147
				ap->loglen = 0;
148
				break;
149
			case 'w':
150
			case '2':
151
				ap->loglen = 1;
152
				break;
153
			case 'l':
154
			case '4':
155
				ap->loglen = 2;
156
				break;
157
			case 'v':
158
			case '8':
159
				ap->loglen = 3;
160
				break;
161
			default:
162
			Usage:
163
   fprint(2, "usage: xd [-u] [-r] [-s] [-a{odx}] [-c|{b1w2l4v8}{odx}] ... file ...\n");
164
				exits("usage");
165
			}
166
			argv[0]++;
167
		}
168
		if(ap->chartype == TRune)
169
			ap->fn = fmtr;
170
		else if(ap->chartype == TAscii)
171
			ap->fn = fmtc;
172
		else
173
			ap->fn = fmt[ap->loglen];
174
		ap->fmt = dfmt[ap->loglen][ap->base];
175
		ap->afmt = afmt[ap>arg][abase];
176
	}
177
	if(narg == 0)
178
		initarg();
179
	if(argc == 1)
180
		err = xd(0, 0);
181
	else if(argc == 2)
182
		err = xd(argv[1], 0);
183
	else for(i=1; i<argc; i++)
184
		err |= xd(argv[i], 1);
185
	exits(err? "error" : 0);
186
}
187
 
188
void
189
initarg(void)
190
{
191
	Arg *ap;
192
 
193
	ap = &arg[narg++];
194
	if(narg >= Narg){
195
		fprint(2, "xd: too many formats (max %d)\n", Narg);
196
		exits("usage");
197
	}
198
	ap->chartype = TNone;
199
	ap->loglen = 2;
200
	ap->base = 2;
201
	ap->fn = fmt2;
202
	ap->fmt = dfmt[ap->loglen][ap->base];
203
	ap->afmt = afmt[narg>1][abase];
204
}
205
 
206
int
207
xd(char *name, int title)
208
{
209
	int fd;
210
	int i, star, nsee, nleft;
211
	Arg *ap;
212
	Biobuf *bp;
213
 
214
	fd = 0;
215
	if(name){
216
		bp = Bopen(name, OREAD);
217
		if(bp == 0){
218
			fprint(2, "xd: can't open %s\n", name);
219
			return 1;
220
		}
221
	}else{
222
		bp = &bin;
223
		Binit(bp, fd, OREAD);
224
	}
225
	if(title)
226
		xprint("%s\n", name);
227
	addr = 0;
228
	star = 0;
229
	nsee = 16;
230
	nleft = 0;
231
	/* read 32 but see only 16 so that runes are happy */
232
	while((ndata=Bread(bp, data + nleft, 32 - nleft)) >= 0){
233
		ndata += nleft;
234
		nleft = 0;
235
		nread = ndata;
236
		if(ndata>nsee)
237
			ndata = nsee;
238
		else if(ndata<nsee)
239
			for(i=ndata; i<nsee; i++)
240
				data[i] = 0;
241
		if(swizzle)
242
			swizz();
243
		if(ndata==nsee && repeats){
244
			if(addr>0 && data[0]==odata[0]){
245
				for(i=1; i<nsee; i++)
246
					if(data[i] != odata[i])
247
						break;
248
				if(i == nsee){
249
					addr += nsee;
250
					if(star == 0){
251
						star++;
252
						xprint("*\n", 0);
253
					}
254
					continue;
255
				}
256
			}
257
			for(i=0; i<nsee; i++)
258
				odata[i] = data[i];
259
			star = 0;
260
		}
261
		for(ap=arg; ap<&arg[narg]; ap++){
262
			xprint(ap->afmt, addr);
263
			(*ap->fn)(ap->fmt);
264
			xprint("\n", 0);
265
			if(flush)
266
				Bflush(&bout);
267
		}
268
		addr += ndata;
269
		if(ndata<nsee){
270
			xprint(afmt[0][abase], addr);
271
			xprint("\n", 0);
272
			if(flush)
273
				Bflush(&bout);
274
			break;
275
		}
276
		if(nread>nsee){
277
			nleft = nread - nsee;
278
			memmove(data, data + nsee, nleft);
279
		}
280
	}
281
	Bterm(bp);
282
	return 0;
283
}
284
 
285
void
286
swizz(void)
287
{
288
	uchar *p, *q;
289
	int i;
290
	uchar swdata[16];
291
 
292
	p = data;
293
	q = swdata;
294
	for(i=0; i<16; i++)
295
		*q++ = *p++;
296
	p = data;
297
	q = swdata;
298
	for(i=0; i<4; i++){
299
		p[0] = q[3];
300
		p[1] = q[2];
301
		p[2] = q[1];
302
		p[3] = q[0];
303
		p += 4;
304
		q += 4;
305
	}
306
}
307
 
308
void
309
fmt0(char *f)
310
{
311
	int i;
312
	for(i=0; i<ndata; i++)
313
		xprint(f, data[i]);
314
}
315
 
316
void
317
fmt1(char *f)
318
{
319
	int i;
320
	for(i=0; i<ndata; i+=sizeof(ushort))
321
		xprint(f, (data[i]<<8)|data[i+1]);
322
}
323
 
324
void
325
fmt2(char *f)
326
{
327
	int i;
328
	for(i=0; i<ndata; i+=sizeof(ulong))
329
		xprint(f, (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3]);
330
}
331
 
332
void
333
fmt3(char *f)
334
{
335
	int i;
336
	uvlong v;
337
 
338
	for(i=0; i<ndata; i+=sizeof(uvlong)){
339
		v = (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3];
340
		v <<= 32;
341
		v |= (data[i+4]<<24)|(data[i+1+4]<<16)|(data[i+2+4]<<8)|data[i+3+4];
342
		if(Bprint(&bout, f, v)<0){
343
			fprint(2, "xd: i/o error\n");
344
			exits("i/o error");
345
		}
346
	}
347
}
348
 
349
void
350
onefmtc(uchar c)
351
{
352
	switch(c){
353
	case '\t':
354
		xprint(cfmt[1][2], "\\t");
355
		break;
356
	case '\r':
357
		xprint(cfmt[1][2], "\\r");
358
		break;
359
	case '\n':
360
		xprint(cfmt[1][2], "\\n");
361
		break;
362
	case '\b':
363
		xprint(cfmt[1][2], "\\b");
364
		break;
365
	default:
366
		if(c>=0x7F || ' '>c)
367
			xprint(cfmt[2][2], c);
368
		else
369
			xprint(cfmt[0][2], c);
370
		break;
371
	}
372
}
373
 
374
void
375
fmtc(char *f)
376
{
377
	int i;
378
 
379
	USED(f);
380
	for(i=0; i<ndata; i++)
381
		onefmtc(data[i]);
382
}
383
 
384
void
385
fmtr(char *f)
386
{
387
	int i, w, cw;
388
	Rune r;
389
	static int nstart;
390
 
391
	USED(f);
392
	if(nstart)	
393
		xprint("%*c", 3*nstart, ' ');
394
	for(i=nstart; i<ndata; )
395
		if(data[i] < Runeself)
396
			onefmtc(data[i++]);
397
		else{
398
			w = chartorune(&r, (char *)data+i);
399
			if(w == 1 || i + w>nread)
400
				onefmtc(data[i++]);
401
			else{
402
				cw = w;
403
				if(i + w>ndata)
404
					cw = ndata - i;
405
				xprint(rfmt[0][0], r);	
406
				xprint("%*c", 3*cw-3, ' ');
407
				i += w;
408
			}
409
		}
410
	if(i > ndata)
411
		nstart = i - ndata;
412
	else
413
		nstart = 0;
414
}
415
 
416
void
417
xprint(char *fmt, ...)
418
{
419
	va_list arglist;
420
 
421
	va_start(arglist, fmt);
422
	if(Bvprint(&bout, fmt, arglist)<0){
423
		fprint(2, "xd: i/o error\n");
424
		exits("i/o error");
425
	}
426
	va_end(arglist);
427
}