xref: /plan9/sys/src/cmd/xd.c (revision 4db25db672e11d72a878263ef7c92def5c56957b)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier 
5*4db25db6SDavid du Colombier uchar		odata[16];
6*4db25db6SDavid du Colombier uchar		data[32];
73e12c5d1SDavid du Colombier int		ndata;
8*4db25db6SDavid du Colombier int		nread;
9*4db25db6SDavid du Colombier ulong		addr;
103e12c5d1SDavid du Colombier int		repeats;
113e12c5d1SDavid du Colombier int		swizzle;
123e12c5d1SDavid du Colombier int		flush;
133e12c5d1SDavid du Colombier int		abase=2;
143e12c5d1SDavid du Colombier int		xd(char *, int);
15af2e6ba6SDavid du Colombier void		xprint(char *, ...);
163e12c5d1SDavid du Colombier void		initarg(void), swizz(void);
173e12c5d1SDavid du Colombier enum{
18*4db25db6SDavid du Colombier 	Narg=10,
19*4db25db6SDavid du Colombier 
20*4db25db6SDavid du Colombier 	TNone=0,
21*4db25db6SDavid du Colombier 	TAscii,
22*4db25db6SDavid du Colombier 	TRune,
233e12c5d1SDavid du Colombier };
243e12c5d1SDavid du Colombier typedef struct Arg Arg;
253e12c5d1SDavid du Colombier typedef void fmtfn(char *);
263e12c5d1SDavid du Colombier struct Arg
273e12c5d1SDavid du Colombier {
28*4db25db6SDavid du Colombier 	int	chartype;		/* TNone, TAscii, TRunes */
29219b2ee8SDavid du Colombier 	int	loglen;		/* 0==1, 1==2, 2==4, 3==8 */
303e12c5d1SDavid du Colombier 	int	base;		/* 0==8, 1==10, 2==16 */
313e12c5d1SDavid du Colombier 	fmtfn	*fn;		/* function to call with data */
323e12c5d1SDavid du Colombier 	char	*afmt;		/* format to use to print address */
333e12c5d1SDavid du Colombier 	char	*fmt;		/* format to use to print data */
343e12c5d1SDavid du Colombier }arg[Narg];
353e12c5d1SDavid du Colombier int	narg;
363e12c5d1SDavid du Colombier 
37*4db25db6SDavid du Colombier fmtfn	fmt0, fmt1, fmt2, fmt3, fmtc, fmtr;
38219b2ee8SDavid du Colombier fmtfn *fmt[4] = {
393e12c5d1SDavid du Colombier 	fmt0,
403e12c5d1SDavid du Colombier 	fmt1,
41219b2ee8SDavid du Colombier 	fmt2,
42219b2ee8SDavid du Colombier 	fmt3
433e12c5d1SDavid du Colombier };
443e12c5d1SDavid du Colombier 
45219b2ee8SDavid du Colombier char *dfmt[4][3] = {
463e12c5d1SDavid du Colombier 	" %.3uo",	" %.3ud",	" %.2ux",
473e12c5d1SDavid du Colombier 	" %.6uo",	" %.5ud",	" %.4ux",
483e12c5d1SDavid du Colombier 	" %.11luo",	" %.10lud",	" %.8lux",
49219b2ee8SDavid du Colombier 	" %.22lluo",	" %.20llud",	" %.16llux",
503e12c5d1SDavid du Colombier };
513e12c5d1SDavid du Colombier 
523e12c5d1SDavid du Colombier char *cfmt[3][3] = {
533e12c5d1SDavid du Colombier 	"   %c",	"   %c", 	"  %c",
543e12c5d1SDavid du Colombier 	" %.3s",	" %.3s",	" %.2s",
553e12c5d1SDavid du Colombier 	" %.3uo",	" %.3ud",	" %.2ux",
563e12c5d1SDavid du Colombier };
573e12c5d1SDavid du Colombier 
58*4db25db6SDavid du Colombier char *rfmt[1][1] = {
59*4db25db6SDavid du Colombier 	" %2.2C",
60*4db25db6SDavid du Colombier };
61*4db25db6SDavid du Colombier 
623e12c5d1SDavid du Colombier char *afmt[2][3] = {
633e12c5d1SDavid du Colombier 	"%.7luo ",	"%.7lud ",	"%.7lux ",
643e12c5d1SDavid du Colombier 	"%7luo ",	"%7lud ",	"%7lux ",
653e12c5d1SDavid du Colombier };
663e12c5d1SDavid du Colombier 
673e12c5d1SDavid du Colombier Biobuf	bin;
683e12c5d1SDavid du Colombier Biobuf	bout;
693e12c5d1SDavid du Colombier 
703e12c5d1SDavid du Colombier void
main(int argc,char * argv[])713e12c5d1SDavid du Colombier main(int argc, char *argv[])
723e12c5d1SDavid du Colombier {
733e12c5d1SDavid du Colombier 	int i, err;
743e12c5d1SDavid du Colombier 	Arg *ap;
753e12c5d1SDavid du Colombier 
763e12c5d1SDavid du Colombier 	Binit(&bout, 1, OWRITE);
773e12c5d1SDavid du Colombier 	err = 0;
78219b2ee8SDavid du Colombier 	ap = 0;
793e12c5d1SDavid du Colombier 	while(argc>1 && argv[1][0]=='-' && argv[1][1]){
803e12c5d1SDavid du Colombier 		--argc;
813e12c5d1SDavid du Colombier 		argv++;
823e12c5d1SDavid du Colombier 		argv[0]++;
833e12c5d1SDavid du Colombier 		if(argv[0][0] == 'r'){
843e12c5d1SDavid du Colombier 			repeats = 1;
853e12c5d1SDavid du Colombier 			if(argv[0][1])
863e12c5d1SDavid du Colombier 				goto Usage;
873e12c5d1SDavid du Colombier 			continue;
883e12c5d1SDavid du Colombier 		}
893e12c5d1SDavid du Colombier 		if(argv[0][0] == 's'){
903e12c5d1SDavid du Colombier 			swizzle = 1;
913e12c5d1SDavid du Colombier 			if(argv[0][1])
923e12c5d1SDavid du Colombier 				goto Usage;
933e12c5d1SDavid du Colombier 			continue;
943e12c5d1SDavid du Colombier 		}
953e12c5d1SDavid du Colombier 		if(argv[0][0] == 'u'){
963e12c5d1SDavid du Colombier 			flush = 1;
973e12c5d1SDavid du Colombier 			if(argv[0][1])
983e12c5d1SDavid du Colombier 				goto Usage;
993e12c5d1SDavid du Colombier 			continue;
1003e12c5d1SDavid du Colombier 		}
1013e12c5d1SDavid du Colombier 		if(argv[0][0] == 'a'){
1023e12c5d1SDavid du Colombier 			argv[0]++;
1033e12c5d1SDavid du Colombier 			switch(argv[0][0]){
1043e12c5d1SDavid du Colombier 			case 'o':
1053e12c5d1SDavid du Colombier 				abase = 0;
1063e12c5d1SDavid du Colombier 				break;
1073e12c5d1SDavid du Colombier 			case 'd':
1083e12c5d1SDavid du Colombier 				abase = 1;
1093e12c5d1SDavid du Colombier 				break;
1103e12c5d1SDavid du Colombier 			case 'x':
1113e12c5d1SDavid du Colombier 				abase = 2;
1123e12c5d1SDavid du Colombier 				break;
1133e12c5d1SDavid du Colombier 			default:
1143e12c5d1SDavid du Colombier 				goto Usage;
1153e12c5d1SDavid du Colombier 			}
1163e12c5d1SDavid du Colombier 			if(argv[0][1])
1173e12c5d1SDavid du Colombier 				goto Usage;
1183e12c5d1SDavid du Colombier 			continue;
1193e12c5d1SDavid du Colombier 		}
1203e12c5d1SDavid du Colombier 		ap = &arg[narg];
1213e12c5d1SDavid du Colombier 		initarg();
1223e12c5d1SDavid du Colombier 		while(argv[0][0]){
1233e12c5d1SDavid du Colombier 			switch(argv[0][0]){
1243e12c5d1SDavid du Colombier 			case 'c':
125*4db25db6SDavid du Colombier 				ap->chartype = TAscii;
126*4db25db6SDavid du Colombier 				ap->loglen = 0;
127*4db25db6SDavid du Colombier 				if(argv[0][1] || argv[0][-1]!='-')
128*4db25db6SDavid du Colombier 					goto Usage;
129*4db25db6SDavid du Colombier 				break;
130*4db25db6SDavid du Colombier 			case 'R':
131*4db25db6SDavid du Colombier 				ap->chartype = TRune;
1323e12c5d1SDavid du Colombier 				ap->loglen = 0;
1333e12c5d1SDavid du Colombier 				if(argv[0][1] || argv[0][-1]!='-')
1343e12c5d1SDavid du Colombier 					goto Usage;
1353e12c5d1SDavid du Colombier 				break;
1363e12c5d1SDavid du Colombier 			case 'o':
1373e12c5d1SDavid du Colombier 				ap->base = 0;
1383e12c5d1SDavid du Colombier 				break;
1393e12c5d1SDavid du Colombier 			case 'd':
1403e12c5d1SDavid du Colombier 				ap->base = 1;
1413e12c5d1SDavid du Colombier 				break;
1423e12c5d1SDavid du Colombier 			case 'x':
1433e12c5d1SDavid du Colombier 				ap->base = 2;
1443e12c5d1SDavid du Colombier 				break;
1453e12c5d1SDavid du Colombier 			case 'b':
1463e12c5d1SDavid du Colombier 			case '1':
1473e12c5d1SDavid du Colombier 				ap->loglen = 0;
1483e12c5d1SDavid du Colombier 				break;
1493e12c5d1SDavid du Colombier 			case 'w':
1503e12c5d1SDavid du Colombier 			case '2':
1513e12c5d1SDavid du Colombier 				ap->loglen = 1;
1523e12c5d1SDavid du Colombier 				break;
1533e12c5d1SDavid du Colombier 			case 'l':
1543e12c5d1SDavid du Colombier 			case '4':
1553e12c5d1SDavid du Colombier 				ap->loglen = 2;
1563e12c5d1SDavid du Colombier 				break;
157219b2ee8SDavid du Colombier 			case 'v':
158219b2ee8SDavid du Colombier 			case '8':
159219b2ee8SDavid du Colombier 				ap->loglen = 3;
160219b2ee8SDavid du Colombier 				break;
1613e12c5d1SDavid du Colombier 			default:
1623e12c5d1SDavid du Colombier 			Usage:
163219b2ee8SDavid du Colombier    fprint(2, "usage: xd [-u] [-r] [-s] [-a{odx}] [-c|{b1w2l4v8}{odx}] ... file ...\n");
1643e12c5d1SDavid du Colombier 				exits("usage");
1653e12c5d1SDavid du Colombier 			}
1663e12c5d1SDavid du Colombier 			argv[0]++;
1673e12c5d1SDavid du Colombier 		}
168*4db25db6SDavid du Colombier 		if(ap->chartype == TRune)
169*4db25db6SDavid du Colombier 			ap->fn = fmtr;
170*4db25db6SDavid du Colombier 		else if(ap->chartype == TAscii)
1713e12c5d1SDavid du Colombier 			ap->fn = fmtc;
1723e12c5d1SDavid du Colombier 		else
1733e12c5d1SDavid du Colombier 			ap->fn = fmt[ap->loglen];
1743e12c5d1SDavid du Colombier 		ap->fmt = dfmt[ap->loglen][ap->base];
1753e12c5d1SDavid du Colombier 		ap->afmt = afmt[ap>arg][abase];
1763e12c5d1SDavid du Colombier 	}
1773e12c5d1SDavid du Colombier 	if(narg == 0)
1783e12c5d1SDavid du Colombier 		initarg();
1793e12c5d1SDavid du Colombier 	if(argc == 1)
1803e12c5d1SDavid du Colombier 		err = xd(0, 0);
1813e12c5d1SDavid du Colombier 	else if(argc == 2)
1823e12c5d1SDavid du Colombier 		err = xd(argv[1], 0);
1833e12c5d1SDavid du Colombier 	else for(i=1; i<argc; i++)
1843e12c5d1SDavid du Colombier 		err |= xd(argv[i], 1);
1853e12c5d1SDavid du Colombier 	exits(err? "error" : 0);
1863e12c5d1SDavid du Colombier }
1873e12c5d1SDavid du Colombier 
1883e12c5d1SDavid du Colombier void
initarg(void)1893e12c5d1SDavid du Colombier initarg(void)
1903e12c5d1SDavid du Colombier {
1913e12c5d1SDavid du Colombier 	Arg *ap;
1923e12c5d1SDavid du Colombier 
1933e12c5d1SDavid du Colombier 	ap = &arg[narg++];
1943e12c5d1SDavid du Colombier 	if(narg >= Narg){
1953e12c5d1SDavid du Colombier 		fprint(2, "xd: too many formats (max %d)\n", Narg);
1963e12c5d1SDavid du Colombier 		exits("usage");
1973e12c5d1SDavid du Colombier 	}
198*4db25db6SDavid du Colombier 	ap->chartype = TNone;
1993e12c5d1SDavid du Colombier 	ap->loglen = 2;
2003e12c5d1SDavid du Colombier 	ap->base = 2;
2013e12c5d1SDavid du Colombier 	ap->fn = fmt2;
2023e12c5d1SDavid du Colombier 	ap->fmt = dfmt[ap->loglen][ap->base];
2033e12c5d1SDavid du Colombier 	ap->afmt = afmt[narg>1][abase];
2043e12c5d1SDavid du Colombier }
2053e12c5d1SDavid du Colombier 
2063e12c5d1SDavid du Colombier int
xd(char * name,int title)2073e12c5d1SDavid du Colombier xd(char *name, int title)
2083e12c5d1SDavid du Colombier {
2093e12c5d1SDavid du Colombier 	int fd;
210*4db25db6SDavid du Colombier 	int i, star, nsee, nleft;
2113e12c5d1SDavid du Colombier 	Arg *ap;
212219b2ee8SDavid du Colombier 	Biobuf *bp;
2133e12c5d1SDavid du Colombier 
2143e12c5d1SDavid du Colombier 	fd = 0;
215219b2ee8SDavid du Colombier 	if(name){
216219b2ee8SDavid du Colombier 		bp = Bopen(name, OREAD);
217219b2ee8SDavid du Colombier 		if(bp == 0){
2183e12c5d1SDavid du Colombier 			fprint(2, "xd: can't open %s\n", name);
2193e12c5d1SDavid du Colombier 			return 1;
2203e12c5d1SDavid du Colombier 		}
221219b2ee8SDavid du Colombier 	}else{
222219b2ee8SDavid du Colombier 		bp = &bin;
223219b2ee8SDavid du Colombier 		Binit(bp, fd, OREAD);
224219b2ee8SDavid du Colombier 	}
2253e12c5d1SDavid du Colombier 	if(title)
226af2e6ba6SDavid du Colombier 		xprint("%s\n", name);
2273e12c5d1SDavid du Colombier 	addr = 0;
2283e12c5d1SDavid du Colombier 	star = 0;
229*4db25db6SDavid du Colombier 	nsee = 16;
230*4db25db6SDavid du Colombier 	nleft = 0;
231*4db25db6SDavid du Colombier 	/* read 32 but see only 16 so that runes are happy */
232*4db25db6SDavid du Colombier 	while((ndata=Bread(bp, data + nleft, 32 - nleft)) >= 0){
233*4db25db6SDavid du Colombier 		ndata += nleft;
234*4db25db6SDavid du Colombier 		nleft = 0;
235*4db25db6SDavid du Colombier 		nread = ndata;
236*4db25db6SDavid du Colombier 		if(ndata>nsee)
237*4db25db6SDavid du Colombier 			ndata = nsee;
238*4db25db6SDavid du Colombier 		else if(ndata<nsee)
239*4db25db6SDavid du Colombier 			for(i=ndata; i<nsee; i++)
2403e12c5d1SDavid du Colombier 				data[i] = 0;
2413e12c5d1SDavid du Colombier 		if(swizzle)
2423e12c5d1SDavid du Colombier 			swizz();
243*4db25db6SDavid du Colombier 		if(ndata==nsee && repeats){
2443e12c5d1SDavid du Colombier 			if(addr>0 && data[0]==odata[0]){
245*4db25db6SDavid du Colombier 				for(i=1; i<nsee; i++)
2463e12c5d1SDavid du Colombier 					if(data[i] != odata[i])
2473e12c5d1SDavid du Colombier 						break;
248*4db25db6SDavid du Colombier 				if(i == nsee){
249*4db25db6SDavid du Colombier 					addr += nsee;
2503e12c5d1SDavid du Colombier 					if(star == 0){
2513e12c5d1SDavid du Colombier 						star++;
2523e12c5d1SDavid du Colombier 						xprint("*\n", 0);
2533e12c5d1SDavid du Colombier 					}
2543e12c5d1SDavid du Colombier 					continue;
2553e12c5d1SDavid du Colombier 				}
2563e12c5d1SDavid du Colombier 			}
257*4db25db6SDavid du Colombier 			for(i=0; i<nsee; i++)
2583e12c5d1SDavid du Colombier 				odata[i] = data[i];
2593e12c5d1SDavid du Colombier 			star = 0;
2603e12c5d1SDavid du Colombier 		}
2613e12c5d1SDavid du Colombier 		for(ap=arg; ap<&arg[narg]; ap++){
2623e12c5d1SDavid du Colombier 			xprint(ap->afmt, addr);
2633e12c5d1SDavid du Colombier 			(*ap->fn)(ap->fmt);
2643e12c5d1SDavid du Colombier 			xprint("\n", 0);
2653e12c5d1SDavid du Colombier 			if(flush)
2663e12c5d1SDavid du Colombier 				Bflush(&bout);
2673e12c5d1SDavid du Colombier 		}
2683e12c5d1SDavid du Colombier 		addr += ndata;
269*4db25db6SDavid du Colombier 		if(ndata<nsee){
2703e12c5d1SDavid du Colombier 			xprint(afmt[0][abase], addr);
2713e12c5d1SDavid du Colombier 			xprint("\n", 0);
2723e12c5d1SDavid du Colombier 			if(flush)
2733e12c5d1SDavid du Colombier 				Bflush(&bout);
2743e12c5d1SDavid du Colombier 			break;
2753e12c5d1SDavid du Colombier 		}
276*4db25db6SDavid du Colombier 		if(nread>nsee){
277*4db25db6SDavid du Colombier 			nleft = nread - nsee;
278*4db25db6SDavid du Colombier 			memmove(data, data + nsee, nleft);
279*4db25db6SDavid du Colombier 		}
2803e12c5d1SDavid du Colombier 	}
281219b2ee8SDavid du Colombier 	Bterm(bp);
2823e12c5d1SDavid du Colombier 	return 0;
2833e12c5d1SDavid du Colombier }
2843e12c5d1SDavid du Colombier 
2853e12c5d1SDavid du Colombier void
swizz(void)2863e12c5d1SDavid du Colombier swizz(void)
2873e12c5d1SDavid du Colombier {
2883e12c5d1SDavid du Colombier 	uchar *p, *q;
2893e12c5d1SDavid du Colombier 	int i;
2903e12c5d1SDavid du Colombier 	uchar swdata[16];
2913e12c5d1SDavid du Colombier 
2923e12c5d1SDavid du Colombier 	p = data;
2933e12c5d1SDavid du Colombier 	q = swdata;
2943e12c5d1SDavid du Colombier 	for(i=0; i<16; i++)
2953e12c5d1SDavid du Colombier 		*q++ = *p++;
2963e12c5d1SDavid du Colombier 	p = data;
2973e12c5d1SDavid du Colombier 	q = swdata;
2983e12c5d1SDavid du Colombier 	for(i=0; i<4; i++){
2993e12c5d1SDavid du Colombier 		p[0] = q[3];
3003e12c5d1SDavid du Colombier 		p[1] = q[2];
3013e12c5d1SDavid du Colombier 		p[2] = q[1];
3023e12c5d1SDavid du Colombier 		p[3] = q[0];
3033e12c5d1SDavid du Colombier 		p += 4;
3043e12c5d1SDavid du Colombier 		q += 4;
3053e12c5d1SDavid du Colombier 	}
3063e12c5d1SDavid du Colombier }
3073e12c5d1SDavid du Colombier 
3083e12c5d1SDavid du Colombier void
fmt0(char * f)3093e12c5d1SDavid du Colombier fmt0(char *f)
3103e12c5d1SDavid du Colombier {
3113e12c5d1SDavid du Colombier 	int i;
3123e12c5d1SDavid du Colombier 	for(i=0; i<ndata; i++)
3133e12c5d1SDavid du Colombier 		xprint(f, data[i]);
3143e12c5d1SDavid du Colombier }
3153e12c5d1SDavid du Colombier 
3163e12c5d1SDavid du Colombier void
fmt1(char * f)3173e12c5d1SDavid du Colombier fmt1(char *f)
3183e12c5d1SDavid du Colombier {
3193e12c5d1SDavid du Colombier 	int i;
320*4db25db6SDavid du Colombier 	for(i=0; i<ndata; i+=sizeof(ushort))
3213e12c5d1SDavid du Colombier 		xprint(f, (data[i]<<8)|data[i+1]);
3223e12c5d1SDavid du Colombier }
3233e12c5d1SDavid du Colombier 
3243e12c5d1SDavid du Colombier void
fmt2(char * f)3253e12c5d1SDavid du Colombier fmt2(char *f)
3263e12c5d1SDavid du Colombier {
3273e12c5d1SDavid du Colombier 	int i;
328*4db25db6SDavid du Colombier 	for(i=0; i<ndata; i+=sizeof(ulong))
3293e12c5d1SDavid du Colombier 		xprint(f, (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3]);
3303e12c5d1SDavid du Colombier }
3313e12c5d1SDavid du Colombier 
3323e12c5d1SDavid du Colombier void
fmt3(char * f)333219b2ee8SDavid du Colombier fmt3(char *f)
334219b2ee8SDavid du Colombier {
335219b2ee8SDavid du Colombier 	int i;
336*4db25db6SDavid du Colombier 	uvlong v;
337*4db25db6SDavid du Colombier 
338*4db25db6SDavid du Colombier 	for(i=0; i<ndata; i+=sizeof(uvlong)){
339219b2ee8SDavid du Colombier 		v = (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3];
340219b2ee8SDavid du Colombier 		v <<= 32;
341219b2ee8SDavid du Colombier 		v |= (data[i+4]<<24)|(data[i+1+4]<<16)|(data[i+2+4]<<8)|data[i+3+4];
342219b2ee8SDavid du Colombier 		if(Bprint(&bout, f, v)<0){
343219b2ee8SDavid du Colombier 			fprint(2, "xd: i/o error\n");
344219b2ee8SDavid du Colombier 			exits("i/o error");
345219b2ee8SDavid du Colombier 		}
346219b2ee8SDavid du Colombier 	}
347219b2ee8SDavid du Colombier }
348219b2ee8SDavid du Colombier 
349219b2ee8SDavid du Colombier void
onefmtc(uchar c)350*4db25db6SDavid du Colombier onefmtc(uchar c)
3513e12c5d1SDavid du Colombier {
352*4db25db6SDavid du Colombier 	switch(c){
3533e12c5d1SDavid du Colombier 	case '\t':
354af2e6ba6SDavid du Colombier 		xprint(cfmt[1][2], "\\t");
3553e12c5d1SDavid du Colombier 		break;
3563e12c5d1SDavid du Colombier 	case '\r':
357af2e6ba6SDavid du Colombier 		xprint(cfmt[1][2], "\\r");
3583e12c5d1SDavid du Colombier 		break;
3593e12c5d1SDavid du Colombier 	case '\n':
360af2e6ba6SDavid du Colombier 		xprint(cfmt[1][2], "\\n");
3613e12c5d1SDavid du Colombier 		break;
3623e12c5d1SDavid du Colombier 	case '\b':
363af2e6ba6SDavid du Colombier 		xprint(cfmt[1][2], "\\b");
3643e12c5d1SDavid du Colombier 		break;
3653e12c5d1SDavid du Colombier 	default:
366*4db25db6SDavid du Colombier 		if(c>=0x7F || ' '>c)
367*4db25db6SDavid du Colombier 			xprint(cfmt[2][2], c);
3683e12c5d1SDavid du Colombier 		else
369*4db25db6SDavid du Colombier 			xprint(cfmt[0][2], c);
3703e12c5d1SDavid du Colombier 		break;
3713e12c5d1SDavid du Colombier 	}
3723e12c5d1SDavid du Colombier }
3733e12c5d1SDavid du Colombier 
3743e12c5d1SDavid du Colombier void
fmtc(char * f)375*4db25db6SDavid du Colombier fmtc(char *f)
376*4db25db6SDavid du Colombier {
377*4db25db6SDavid du Colombier 	int i;
378*4db25db6SDavid du Colombier 
379*4db25db6SDavid du Colombier 	USED(f);
380*4db25db6SDavid du Colombier 	for(i=0; i<ndata; i++)
381*4db25db6SDavid du Colombier 		onefmtc(data[i]);
382*4db25db6SDavid du Colombier }
383*4db25db6SDavid du Colombier 
384*4db25db6SDavid du Colombier void
fmtr(char * f)385*4db25db6SDavid du Colombier fmtr(char *f)
386*4db25db6SDavid du Colombier {
387*4db25db6SDavid du Colombier 	int i, w, cw;
388*4db25db6SDavid du Colombier 	Rune r;
389*4db25db6SDavid du Colombier 	static int nstart;
390*4db25db6SDavid du Colombier 
391*4db25db6SDavid du Colombier 	USED(f);
392*4db25db6SDavid du Colombier 	if(nstart)
393*4db25db6SDavid du Colombier 		xprint("%*c", 3*nstart, ' ');
394*4db25db6SDavid du Colombier 	for(i=nstart; i<ndata; )
395*4db25db6SDavid du Colombier 		if(data[i] < Runeself)
396*4db25db6SDavid du Colombier 			onefmtc(data[i++]);
397*4db25db6SDavid du Colombier 		else{
398*4db25db6SDavid du Colombier 			w = chartorune(&r, (char *)data+i);
399*4db25db6SDavid du Colombier 			if(w == 1 || i + w>nread)
400*4db25db6SDavid du Colombier 				onefmtc(data[i++]);
401*4db25db6SDavid du Colombier 			else{
402*4db25db6SDavid du Colombier 				cw = w;
403*4db25db6SDavid du Colombier 				if(i + w>ndata)
404*4db25db6SDavid du Colombier 					cw = ndata - i;
405*4db25db6SDavid du Colombier 				xprint(rfmt[0][0], r);
406*4db25db6SDavid du Colombier 				xprint("%*c", 3*cw-3, ' ');
407*4db25db6SDavid du Colombier 				i += w;
408*4db25db6SDavid du Colombier 			}
409*4db25db6SDavid du Colombier 		}
410*4db25db6SDavid du Colombier 	if(i > ndata)
411*4db25db6SDavid du Colombier 		nstart = i - ndata;
412*4db25db6SDavid du Colombier 	else
413*4db25db6SDavid du Colombier 		nstart = 0;
414*4db25db6SDavid du Colombier }
415*4db25db6SDavid du Colombier 
416*4db25db6SDavid du Colombier void
xprint(char * fmt,...)417af2e6ba6SDavid du Colombier xprint(char *fmt, ...)
4183e12c5d1SDavid du Colombier {
419af2e6ba6SDavid du Colombier 	va_list arglist;
420af2e6ba6SDavid du Colombier 
421af2e6ba6SDavid du Colombier 	va_start(arglist, fmt);
422af2e6ba6SDavid du Colombier 	if(Bvprint(&bout, fmt, arglist)<0){
4233e12c5d1SDavid du Colombier 		fprint(2, "xd: i/o error\n");
4243e12c5d1SDavid du Colombier 		exits("i/o error");
4253e12c5d1SDavid du Colombier 	}
426af2e6ba6SDavid du Colombier 	va_end(arglist);
4273e12c5d1SDavid du Colombier }
428