13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
43e12c5d1SDavid du Colombier
5*a1e175a1SDavid du Colombier enum {
6*a1e175a1SDavid du Colombier Nsee = 4*4, /* process this many bytes at a time; see swizz */
7*a1e175a1SDavid du Colombier };
8*a1e175a1SDavid du Colombier
9*a1e175a1SDavid du Colombier uchar odata[Nsee];
10*a1e175a1SDavid du Colombier uchar data[2*Nsee];
113e12c5d1SDavid du Colombier int ndata;
124db25db6SDavid du Colombier int nread;
134db25db6SDavid du Colombier ulong addr;
143e12c5d1SDavid du Colombier int repeats;
153e12c5d1SDavid du Colombier int swizzle;
163e12c5d1SDavid du Colombier int flush;
173e12c5d1SDavid du Colombier int abase=2;
18*a1e175a1SDavid du Colombier
193e12c5d1SDavid du Colombier int xd(char *, int);
20af2e6ba6SDavid du Colombier void xprint(char *, ...);
213e12c5d1SDavid du Colombier void initarg(void), swizz(void);
22*a1e175a1SDavid du Colombier
233e12c5d1SDavid du Colombier enum{
244db25db6SDavid du Colombier Narg=10,
254db25db6SDavid du Colombier
264db25db6SDavid du Colombier TNone=0,
274db25db6SDavid du Colombier TAscii,
284db25db6SDavid du Colombier TRune,
293e12c5d1SDavid du Colombier };
303e12c5d1SDavid du Colombier typedef struct Arg Arg;
313e12c5d1SDavid du Colombier typedef void fmtfn(char *);
323e12c5d1SDavid du Colombier struct Arg
333e12c5d1SDavid du Colombier {
344db25db6SDavid du Colombier int chartype; /* TNone, TAscii, TRunes */
35219b2ee8SDavid du Colombier int loglen; /* 0==1, 1==2, 2==4, 3==8 */
363e12c5d1SDavid du Colombier int base; /* 0==8, 1==10, 2==16 */
373e12c5d1SDavid du Colombier fmtfn *fn; /* function to call with data */
383e12c5d1SDavid du Colombier char *afmt; /* format to use to print address */
393e12c5d1SDavid du Colombier char *fmt; /* format to use to print data */
403e12c5d1SDavid du Colombier }arg[Narg];
413e12c5d1SDavid du Colombier int narg;
423e12c5d1SDavid du Colombier
434db25db6SDavid du Colombier fmtfn fmt0, fmt1, fmt2, fmt3, fmtc, fmtr;
44219b2ee8SDavid du Colombier fmtfn *fmt[4] = {
453e12c5d1SDavid du Colombier fmt0,
463e12c5d1SDavid du Colombier fmt1,
47219b2ee8SDavid du Colombier fmt2,
48219b2ee8SDavid du Colombier fmt3
493e12c5d1SDavid du Colombier };
503e12c5d1SDavid du Colombier
51219b2ee8SDavid du Colombier char *dfmt[4][3] = {
523e12c5d1SDavid du Colombier " %.3uo", " %.3ud", " %.2ux",
533e12c5d1SDavid du Colombier " %.6uo", " %.5ud", " %.4ux",
543e12c5d1SDavid du Colombier " %.11luo", " %.10lud", " %.8lux",
55219b2ee8SDavid du Colombier " %.22lluo", " %.20llud", " %.16llux",
563e12c5d1SDavid du Colombier };
573e12c5d1SDavid du Colombier
583e12c5d1SDavid du Colombier char *cfmt[3][3] = {
593e12c5d1SDavid du Colombier " %c", " %c", " %c",
603e12c5d1SDavid du Colombier " %.3s", " %.3s", " %.2s",
613e12c5d1SDavid du Colombier " %.3uo", " %.3ud", " %.2ux",
623e12c5d1SDavid du Colombier };
633e12c5d1SDavid du Colombier
644db25db6SDavid du Colombier char *rfmt[1][1] = {
654db25db6SDavid du Colombier " %2.2C",
664db25db6SDavid du Colombier };
674db25db6SDavid du Colombier
683e12c5d1SDavid du Colombier char *afmt[2][3] = {
693e12c5d1SDavid du Colombier "%.7luo ", "%.7lud ", "%.7lux ",
703e12c5d1SDavid du Colombier "%7luo ", "%7lud ", "%7lux ",
713e12c5d1SDavid du Colombier };
723e12c5d1SDavid du Colombier
733e12c5d1SDavid du Colombier Biobuf bin;
743e12c5d1SDavid du Colombier Biobuf bout;
753e12c5d1SDavid du Colombier
763e12c5d1SDavid du Colombier void
main(int argc,char * argv[])773e12c5d1SDavid du Colombier main(int argc, char *argv[])
783e12c5d1SDavid du Colombier {
793e12c5d1SDavid du Colombier int i, err;
803e12c5d1SDavid du Colombier Arg *ap;
813e12c5d1SDavid du Colombier
823e12c5d1SDavid du Colombier Binit(&bout, 1, OWRITE);
833e12c5d1SDavid du Colombier err = 0;
84219b2ee8SDavid du Colombier ap = 0;
853e12c5d1SDavid du Colombier while(argc>1 && argv[1][0]=='-' && argv[1][1]){
863e12c5d1SDavid du Colombier --argc;
873e12c5d1SDavid du Colombier argv++;
883e12c5d1SDavid du Colombier argv[0]++;
893e12c5d1SDavid du Colombier if(argv[0][0] == 'r'){
903e12c5d1SDavid du Colombier repeats = 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] == 's'){
963e12c5d1SDavid du Colombier swizzle = 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] == 'u'){
1023e12c5d1SDavid du Colombier flush = 1;
1033e12c5d1SDavid du Colombier if(argv[0][1])
1043e12c5d1SDavid du Colombier goto Usage;
1053e12c5d1SDavid du Colombier continue;
1063e12c5d1SDavid du Colombier }
1073e12c5d1SDavid du Colombier if(argv[0][0] == 'a'){
1083e12c5d1SDavid du Colombier argv[0]++;
1093e12c5d1SDavid du Colombier switch(argv[0][0]){
1103e12c5d1SDavid du Colombier case 'o':
1113e12c5d1SDavid du Colombier abase = 0;
1123e12c5d1SDavid du Colombier break;
1133e12c5d1SDavid du Colombier case 'd':
1143e12c5d1SDavid du Colombier abase = 1;
1153e12c5d1SDavid du Colombier break;
1163e12c5d1SDavid du Colombier case 'x':
1173e12c5d1SDavid du Colombier abase = 2;
1183e12c5d1SDavid du Colombier break;
1193e12c5d1SDavid du Colombier default:
1203e12c5d1SDavid du Colombier goto Usage;
1213e12c5d1SDavid du Colombier }
1223e12c5d1SDavid du Colombier if(argv[0][1])
1233e12c5d1SDavid du Colombier goto Usage;
1243e12c5d1SDavid du Colombier continue;
1253e12c5d1SDavid du Colombier }
1263e12c5d1SDavid du Colombier ap = &arg[narg];
1273e12c5d1SDavid du Colombier initarg();
1283e12c5d1SDavid du Colombier while(argv[0][0]){
1293e12c5d1SDavid du Colombier switch(argv[0][0]){
1303e12c5d1SDavid du Colombier case 'c':
1314db25db6SDavid du Colombier ap->chartype = TAscii;
1324db25db6SDavid du Colombier ap->loglen = 0;
1334db25db6SDavid du Colombier if(argv[0][1] || argv[0][-1]!='-')
1344db25db6SDavid du Colombier goto Usage;
1354db25db6SDavid du Colombier break;
1364db25db6SDavid du Colombier case 'R':
1374db25db6SDavid du Colombier ap->chartype = TRune;
1383e12c5d1SDavid du Colombier ap->loglen = 0;
1393e12c5d1SDavid du Colombier if(argv[0][1] || argv[0][-1]!='-')
1403e12c5d1SDavid du Colombier goto Usage;
1413e12c5d1SDavid du Colombier break;
1423e12c5d1SDavid du Colombier case 'o':
1433e12c5d1SDavid du Colombier ap->base = 0;
1443e12c5d1SDavid du Colombier break;
1453e12c5d1SDavid du Colombier case 'd':
1463e12c5d1SDavid du Colombier ap->base = 1;
1473e12c5d1SDavid du Colombier break;
1483e12c5d1SDavid du Colombier case 'x':
1493e12c5d1SDavid du Colombier ap->base = 2;
1503e12c5d1SDavid du Colombier break;
1513e12c5d1SDavid du Colombier case 'b':
1523e12c5d1SDavid du Colombier case '1':
1533e12c5d1SDavid du Colombier ap->loglen = 0;
1543e12c5d1SDavid du Colombier break;
1553e12c5d1SDavid du Colombier case 'w':
1563e12c5d1SDavid du Colombier case '2':
1573e12c5d1SDavid du Colombier ap->loglen = 1;
1583e12c5d1SDavid du Colombier break;
1593e12c5d1SDavid du Colombier case 'l':
1603e12c5d1SDavid du Colombier case '4':
1613e12c5d1SDavid du Colombier ap->loglen = 2;
1623e12c5d1SDavid du Colombier break;
163219b2ee8SDavid du Colombier case 'v':
164219b2ee8SDavid du Colombier case '8':
165219b2ee8SDavid du Colombier ap->loglen = 3;
166219b2ee8SDavid du Colombier break;
1673e12c5d1SDavid du Colombier default:
1683e12c5d1SDavid du Colombier Usage:
169219b2ee8SDavid du Colombier fprint(2, "usage: xd [-u] [-r] [-s] [-a{odx}] [-c|{b1w2l4v8}{odx}] ... file ...\n");
1703e12c5d1SDavid du Colombier exits("usage");
1713e12c5d1SDavid du Colombier }
1723e12c5d1SDavid du Colombier argv[0]++;
1733e12c5d1SDavid du Colombier }
1744db25db6SDavid du Colombier if(ap->chartype == TRune)
1754db25db6SDavid du Colombier ap->fn = fmtr;
1764db25db6SDavid du Colombier else if(ap->chartype == TAscii)
1773e12c5d1SDavid du Colombier ap->fn = fmtc;
1783e12c5d1SDavid du Colombier else
1793e12c5d1SDavid du Colombier ap->fn = fmt[ap->loglen];
1803e12c5d1SDavid du Colombier ap->fmt = dfmt[ap->loglen][ap->base];
1813e12c5d1SDavid du Colombier ap->afmt = afmt[ap>arg][abase];
1823e12c5d1SDavid du Colombier }
1833e12c5d1SDavid du Colombier if(narg == 0)
1843e12c5d1SDavid du Colombier initarg();
1853e12c5d1SDavid du Colombier if(argc == 1)
1863e12c5d1SDavid du Colombier err = xd(0, 0);
1873e12c5d1SDavid du Colombier else if(argc == 2)
1883e12c5d1SDavid du Colombier err = xd(argv[1], 0);
1893e12c5d1SDavid du Colombier else for(i=1; i<argc; i++)
1903e12c5d1SDavid du Colombier err |= xd(argv[i], 1);
1913e12c5d1SDavid du Colombier exits(err? "error" : 0);
1923e12c5d1SDavid du Colombier }
1933e12c5d1SDavid du Colombier
1943e12c5d1SDavid du Colombier void
initarg(void)1953e12c5d1SDavid du Colombier initarg(void)
1963e12c5d1SDavid du Colombier {
1973e12c5d1SDavid du Colombier Arg *ap;
1983e12c5d1SDavid du Colombier
1993e12c5d1SDavid du Colombier ap = &arg[narg++];
2003e12c5d1SDavid du Colombier if(narg >= Narg){
2013e12c5d1SDavid du Colombier fprint(2, "xd: too many formats (max %d)\n", Narg);
2023e12c5d1SDavid du Colombier exits("usage");
2033e12c5d1SDavid du Colombier }
2044db25db6SDavid du Colombier ap->chartype = TNone;
2053e12c5d1SDavid du Colombier ap->loglen = 2;
2063e12c5d1SDavid du Colombier ap->base = 2;
2073e12c5d1SDavid du Colombier ap->fn = fmt2;
2083e12c5d1SDavid du Colombier ap->fmt = dfmt[ap->loglen][ap->base];
2093e12c5d1SDavid du Colombier ap->afmt = afmt[narg>1][abase];
2103e12c5d1SDavid du Colombier }
2113e12c5d1SDavid du Colombier
212*a1e175a1SDavid du Colombier /*
213*a1e175a1SDavid du Colombier * format the first ndata bytes in data[] (at most Nsee bytes).
214*a1e175a1SDavid du Colombier * increment addr to account for them.
215*a1e175a1SDavid du Colombier */
216*a1e175a1SDavid du Colombier void
fmtdata(void)217*a1e175a1SDavid du Colombier fmtdata(void)
218*a1e175a1SDavid du Colombier {
219*a1e175a1SDavid du Colombier Arg *ap;
220*a1e175a1SDavid du Colombier
221*a1e175a1SDavid du Colombier for(ap=arg; ap<&arg[narg]; ap++){
222*a1e175a1SDavid du Colombier xprint(ap->afmt, addr);
223*a1e175a1SDavid du Colombier (*ap->fn)(ap->fmt);
224*a1e175a1SDavid du Colombier xprint("\n", 0);
225*a1e175a1SDavid du Colombier if(flush)
226*a1e175a1SDavid du Colombier Bflush(&bout);
227*a1e175a1SDavid du Colombier }
228*a1e175a1SDavid du Colombier addr += ndata;
229*a1e175a1SDavid du Colombier if(ndata<Nsee){ /* short read? print fragment */
230*a1e175a1SDavid du Colombier xprint(afmt[0][abase], addr);
231*a1e175a1SDavid du Colombier xprint("\n", 0);
232*a1e175a1SDavid du Colombier if(flush)
233*a1e175a1SDavid du Colombier Bflush(&bout);
234*a1e175a1SDavid du Colombier }
235*a1e175a1SDavid du Colombier }
236*a1e175a1SDavid du Colombier
2373e12c5d1SDavid du Colombier int
xd(char * name,int title)2383e12c5d1SDavid du Colombier xd(char *name, int title)
2393e12c5d1SDavid du Colombier {
240*a1e175a1SDavid du Colombier int fd, star, nleft, doprint;
241219b2ee8SDavid du Colombier Biobuf *bp;
2423e12c5d1SDavid du Colombier
2433e12c5d1SDavid du Colombier fd = 0;
244219b2ee8SDavid du Colombier if(name){
245219b2ee8SDavid du Colombier bp = Bopen(name, OREAD);
246219b2ee8SDavid du Colombier if(bp == 0){
2473e12c5d1SDavid du Colombier fprint(2, "xd: can't open %s\n", name);
2483e12c5d1SDavid du Colombier return 1;
2493e12c5d1SDavid du Colombier }
250219b2ee8SDavid du Colombier }else{
251219b2ee8SDavid du Colombier bp = &bin;
252219b2ee8SDavid du Colombier Binit(bp, fd, OREAD);
253219b2ee8SDavid du Colombier }
2543e12c5d1SDavid du Colombier if(title)
255af2e6ba6SDavid du Colombier xprint("%s\n", name);
2563e12c5d1SDavid du Colombier addr = 0;
2573e12c5d1SDavid du Colombier star = 0;
2584db25db6SDavid du Colombier nleft = 0;
259*a1e175a1SDavid du Colombier /* read 2*Nsee but see only Nsee so that runes are happy */
260*a1e175a1SDavid du Colombier while((ndata=Bread(bp, data + nleft, 2*Nsee - nleft)) >= 0){
2614db25db6SDavid du Colombier ndata += nleft;
2624db25db6SDavid du Colombier nleft = 0;
2634db25db6SDavid du Colombier nread = ndata;
264*a1e175a1SDavid du Colombier if(ndata>Nsee)
265*a1e175a1SDavid du Colombier ndata = Nsee;
266*a1e175a1SDavid du Colombier else if(ndata<Nsee)
267*a1e175a1SDavid du Colombier memset(data + ndata, '\0', Nsee - ndata);
2683e12c5d1SDavid du Colombier if(swizzle)
2693e12c5d1SDavid du Colombier swizz();
270*a1e175a1SDavid du Colombier doprint = 1;
271*a1e175a1SDavid du Colombier if(ndata==Nsee && repeats)
272*a1e175a1SDavid du Colombier if(addr>0 && memcmp(odata, data, Nsee) == 0){
273*a1e175a1SDavid du Colombier doprint = 0;
2743e12c5d1SDavid du Colombier if(star == 0){
2753e12c5d1SDavid du Colombier star++;
2763e12c5d1SDavid du Colombier xprint("*\n", 0);
2773e12c5d1SDavid du Colombier }
278*a1e175a1SDavid du Colombier } else { /* not a repetition */
279*a1e175a1SDavid du Colombier memmove(odata, data, Nsee);
2803e12c5d1SDavid du Colombier star = 0;
2813e12c5d1SDavid du Colombier }
282*a1e175a1SDavid du Colombier if (doprint)
283*a1e175a1SDavid du Colombier fmtdata(); /* also increments addr */
284*a1e175a1SDavid du Colombier else
285*a1e175a1SDavid du Colombier addr += Nsee;
286*a1e175a1SDavid du Colombier if(ndata<Nsee) /* short read? done */
2873e12c5d1SDavid du Colombier break;
288*a1e175a1SDavid du Colombier if(nread>Nsee){
289*a1e175a1SDavid du Colombier nleft = nread - Nsee;
290*a1e175a1SDavid du Colombier memmove(data, data + Nsee, nleft);
2914db25db6SDavid du Colombier }
2923e12c5d1SDavid du Colombier }
293219b2ee8SDavid du Colombier Bterm(bp);
2943e12c5d1SDavid du Colombier return 0;
2953e12c5d1SDavid du Colombier }
2963e12c5d1SDavid du Colombier
2973e12c5d1SDavid du Colombier void
swizz(void)2983e12c5d1SDavid du Colombier swizz(void)
2993e12c5d1SDavid du Colombier {
3003e12c5d1SDavid du Colombier uchar *p, *q;
3013e12c5d1SDavid du Colombier int i;
302*a1e175a1SDavid du Colombier uchar swdata[Nsee];
3033e12c5d1SDavid du Colombier
3043e12c5d1SDavid du Colombier p = data;
3053e12c5d1SDavid du Colombier q = swdata;
306*a1e175a1SDavid du Colombier for(i=0; i<Nsee; i++)
3073e12c5d1SDavid du Colombier *q++ = *p++;
3083e12c5d1SDavid du Colombier p = data;
3093e12c5d1SDavid du Colombier q = swdata;
3103e12c5d1SDavid du Colombier for(i=0; i<4; i++){
3113e12c5d1SDavid du Colombier p[0] = q[3];
3123e12c5d1SDavid du Colombier p[1] = q[2];
3133e12c5d1SDavid du Colombier p[2] = q[1];
3143e12c5d1SDavid du Colombier p[3] = q[0];
3153e12c5d1SDavid du Colombier p += 4;
3163e12c5d1SDavid du Colombier q += 4;
3173e12c5d1SDavid du Colombier }
3183e12c5d1SDavid du Colombier }
3193e12c5d1SDavid du Colombier
3203e12c5d1SDavid du Colombier void
fmt0(char * f)3213e12c5d1SDavid du Colombier fmt0(char *f)
3223e12c5d1SDavid du Colombier {
3233e12c5d1SDavid du Colombier int i;
3243e12c5d1SDavid du Colombier for(i=0; i<ndata; i++)
3253e12c5d1SDavid du Colombier xprint(f, data[i]);
3263e12c5d1SDavid du Colombier }
3273e12c5d1SDavid du Colombier
3283e12c5d1SDavid du Colombier void
fmt1(char * f)3293e12c5d1SDavid du Colombier fmt1(char *f)
3303e12c5d1SDavid du Colombier {
3313e12c5d1SDavid du Colombier int i;
3324db25db6SDavid du Colombier for(i=0; i<ndata; i+=sizeof(ushort))
3333e12c5d1SDavid du Colombier xprint(f, (data[i]<<8)|data[i+1]);
3343e12c5d1SDavid du Colombier }
3353e12c5d1SDavid du Colombier
3363e12c5d1SDavid du Colombier void
fmt2(char * f)3373e12c5d1SDavid du Colombier fmt2(char *f)
3383e12c5d1SDavid du Colombier {
3393e12c5d1SDavid du Colombier int i;
3404db25db6SDavid du Colombier for(i=0; i<ndata; i+=sizeof(ulong))
3413e12c5d1SDavid du Colombier xprint(f, (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3]);
3423e12c5d1SDavid du Colombier }
3433e12c5d1SDavid du Colombier
3443e12c5d1SDavid du Colombier void
fmt3(char * f)345219b2ee8SDavid du Colombier fmt3(char *f)
346219b2ee8SDavid du Colombier {
347219b2ee8SDavid du Colombier int i;
3484db25db6SDavid du Colombier uvlong v;
3494db25db6SDavid du Colombier
3504db25db6SDavid du Colombier for(i=0; i<ndata; i+=sizeof(uvlong)){
351219b2ee8SDavid du Colombier v = (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3];
352219b2ee8SDavid du Colombier v <<= 32;
353219b2ee8SDavid du Colombier v |= (data[i+4]<<24)|(data[i+1+4]<<16)|(data[i+2+4]<<8)|data[i+3+4];
354219b2ee8SDavid du Colombier if(Bprint(&bout, f, v)<0){
355219b2ee8SDavid du Colombier fprint(2, "xd: i/o error\n");
356219b2ee8SDavid du Colombier exits("i/o error");
357219b2ee8SDavid du Colombier }
358219b2ee8SDavid du Colombier }
359219b2ee8SDavid du Colombier }
360219b2ee8SDavid du Colombier
361219b2ee8SDavid du Colombier void
onefmtc(uchar c)3624db25db6SDavid du Colombier onefmtc(uchar c)
3633e12c5d1SDavid du Colombier {
3644db25db6SDavid du Colombier switch(c){
3653e12c5d1SDavid du Colombier case '\t':
366af2e6ba6SDavid du Colombier xprint(cfmt[1][2], "\\t");
3673e12c5d1SDavid du Colombier break;
3683e12c5d1SDavid du Colombier case '\r':
369af2e6ba6SDavid du Colombier xprint(cfmt[1][2], "\\r");
3703e12c5d1SDavid du Colombier break;
3713e12c5d1SDavid du Colombier case '\n':
372af2e6ba6SDavid du Colombier xprint(cfmt[1][2], "\\n");
3733e12c5d1SDavid du Colombier break;
3743e12c5d1SDavid du Colombier case '\b':
375af2e6ba6SDavid du Colombier xprint(cfmt[1][2], "\\b");
3763e12c5d1SDavid du Colombier break;
3773e12c5d1SDavid du Colombier default:
3784db25db6SDavid du Colombier if(c>=0x7F || ' '>c)
3794db25db6SDavid du Colombier xprint(cfmt[2][2], c);
3803e12c5d1SDavid du Colombier else
3814db25db6SDavid du Colombier xprint(cfmt[0][2], c);
3823e12c5d1SDavid du Colombier break;
3833e12c5d1SDavid du Colombier }
3843e12c5d1SDavid du Colombier }
3853e12c5d1SDavid du Colombier
3863e12c5d1SDavid du Colombier void
fmtc(char * f)3874db25db6SDavid du Colombier fmtc(char *f)
3884db25db6SDavid du Colombier {
3894db25db6SDavid du Colombier int i;
3904db25db6SDavid du Colombier
3914db25db6SDavid du Colombier USED(f);
3924db25db6SDavid du Colombier for(i=0; i<ndata; i++)
3934db25db6SDavid du Colombier onefmtc(data[i]);
3944db25db6SDavid du Colombier }
3954db25db6SDavid du Colombier
3964db25db6SDavid du Colombier void
fmtr(char * f)3974db25db6SDavid du Colombier fmtr(char *f)
3984db25db6SDavid du Colombier {
3994db25db6SDavid du Colombier int i, w, cw;
4004db25db6SDavid du Colombier Rune r;
4014db25db6SDavid du Colombier static int nstart;
4024db25db6SDavid du Colombier
4034db25db6SDavid du Colombier USED(f);
4044db25db6SDavid du Colombier if(nstart)
4054db25db6SDavid du Colombier xprint("%*c", 3*nstart, ' ');
4064db25db6SDavid du Colombier for(i=nstart; i<ndata; )
4074db25db6SDavid du Colombier if(data[i] < Runeself)
4084db25db6SDavid du Colombier onefmtc(data[i++]);
4094db25db6SDavid du Colombier else{
4104db25db6SDavid du Colombier w = chartorune(&r, (char *)data+i);
4114db25db6SDavid du Colombier if(w == 1 || i + w>nread)
4124db25db6SDavid du Colombier onefmtc(data[i++]);
4134db25db6SDavid du Colombier else{
4144db25db6SDavid du Colombier cw = w;
4154db25db6SDavid du Colombier if(i + w>ndata)
4164db25db6SDavid du Colombier cw = ndata - i;
4174db25db6SDavid du Colombier xprint(rfmt[0][0], r);
4184db25db6SDavid du Colombier xprint("%*c", 3*cw-3, ' ');
4194db25db6SDavid du Colombier i += w;
4204db25db6SDavid du Colombier }
4214db25db6SDavid du Colombier }
4224db25db6SDavid du Colombier if(i > ndata)
4234db25db6SDavid du Colombier nstart = i - ndata;
4244db25db6SDavid du Colombier else
4254db25db6SDavid du Colombier nstart = 0;
4264db25db6SDavid du Colombier }
4274db25db6SDavid du Colombier
4284db25db6SDavid du Colombier void
xprint(char * fmt,...)429af2e6ba6SDavid du Colombier xprint(char *fmt, ...)
4303e12c5d1SDavid du Colombier {
431af2e6ba6SDavid du Colombier va_list arglist;
432af2e6ba6SDavid du Colombier
433af2e6ba6SDavid du Colombier va_start(arglist, fmt);
434af2e6ba6SDavid du Colombier if(Bvprint(&bout, fmt, arglist)<0){
4353e12c5d1SDavid du Colombier fprint(2, "xd: i/o error\n");
4363e12c5d1SDavid du Colombier exits("i/o error");
4373e12c5d1SDavid du Colombier }
438af2e6ba6SDavid du Colombier va_end(arglist);
4393e12c5d1SDavid du Colombier }
440