xd. add rune formatting, and also add an optional argument to -s, specifying the swab length. the default behavior is not changed. Reference: /n/atom/patch/applied2013/xdrs Date: Thu Aug 1 18:06:42 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/src/cmd/xd.c Thu Aug 1 18:06:16 2013 +++ /sys/src/cmd/xd.c Thu Aug 1 18:06:16 2013 @@ -2,10 +2,11 @@ #include #include -unsigned char odata[16]; -unsigned char data[16]; +uchar odata[16]; +uchar data[32]; int ndata; -unsigned long addr; +int nread; +ulong addr; int repeats; int swizzle; int flush; @@ -14,13 +15,17 @@ void xprint(char *, ...); void initarg(void), swizz(void); enum{ - Narg=10 + Narg=10, + + TNone=0, + TAscii, + TRune, }; typedef struct Arg Arg; typedef void fmtfn(char *); struct Arg { - int ascii; /* 0==none, 1==ascii */ + int chartype; /* TNone, TAscii, TRunes */ int loglen; /* 0==1, 1==2, 2==4, 3==8 */ int base; /* 0==8, 1==10, 2==16 */ fmtfn *fn; /* function to call with data */ @@ -29,7 +34,7 @@ }arg[Narg]; int narg; -fmtfn fmt0, fmt1, fmt2, fmt3, fmtc; +fmtfn fmt0, fmt1, fmt2, fmt3, fmtc, fmtr; fmtfn *fmt[4] = { fmt0, fmt1, @@ -50,6 +55,10 @@ " %.3uo", " %.3ud", " %.2ux", }; +char *rfmt[1][1] = { + " %2.2C", +}; + char *afmt[2][3] = { "%.7luo ", "%.7lud ", "%.7lux ", "%7luo ", "%7lud ", "%7lux ", @@ -77,15 +86,11 @@ goto Usage; continue; } - if(argv[0][0] == 'S'){ - swizzle = 2; - if(argv[0][1]) - goto Usage; - continue; - } if(argv[0][0] == 's'){ swizzle = 4; if(argv[0][1]) + swizzle = atoi(argv[0]+1); + if(swizzle <= 0 || swizzle > 8) goto Usage; continue; } @@ -119,7 +124,13 @@ while(argv[0][0]){ switch(argv[0][0]){ case 'c': - ap->ascii = 1; + ap->chartype = TAscii; + ap->loglen = 0; + if(argv[0][1] || argv[0][-1]!='-') + goto Usage; + break; + case 'R': + ap->chartype = TRune; ap->loglen = 0; if(argv[0][1] || argv[0][-1]!='-') goto Usage; @@ -151,12 +162,14 @@ break; default: Usage: - fprint(2, "usage: xd [-u] [-r] [-s] [-a{odx}] [-c|{b1w2l4v8}{odx}] ... file ...\n"); + fprint(2, "usage: xd [-u] [-r] [-s[n]] [-a{odx}] [-c|-R|{b1w2l4v8}{odx}] ... file ...\n"); exits("usage"); } argv[0]++; } - if(ap->ascii) + if(ap->chartype == TRune) + ap->fn = fmtr; + else if(ap->chartype == TAscii) ap->fn = fmtc; else ap->fn = fmt[ap->loglen]; @@ -184,7 +197,7 @@ fprint(2, "xd: too many formats (max %d)\n", Narg); exits("usage"); } - ap->ascii = 0; + ap->chartype = TNone; ap->loglen = 2; ap->base = 2; ap->fn = fmt2; @@ -196,7 +209,7 @@ xd(char *name, int title) { int fd; - int i, star; + int i, star, nsee, nleft; Arg *ap; Biobuf *bp; @@ -215,19 +228,27 @@ xprint("%s\n", name); addr = 0; star = 0; - while((ndata=Bread(bp, data, 16)) >= 0){ - if(ndata < 16) - for(i=ndata; i<16; i++) + nsee = 16; + nleft = 0; + /* read 32 but see only 16 so that runes are happy */ + while((ndata=Bread(bp, data + nleft, 32 - nleft)) >= 0){ + ndata += nleft; + nleft = 0; + nread = ndata; + if(ndata>nsee) + ndata = nsee; + else if(ndata0 && data[0]==odata[0]){ - for(i=1; i<16; i++) + for(i=1; insee){ + nleft = nread - nsee; + memmove(data, data + nsee, nleft); + } } Bterm(bp); return 0; } -void -swizz2(void) -{ - uchar *p, *q; - int i; - uchar swdata[16]; - - p = data; - q = swdata; - for(i=0; i<16; i++) - *q++ = *p++; - p = data; - q = swdata; - for(i=0; i<8; i++){ - p[0] = q[1]; - p[1] = q[0]; - p += 2; - q += 2; - } -} +uchar order[] = {7, 6, 5, 4, 3, 2, 1, 0}; void -swizz4(void) +swizz(void) { - uchar *p, *q; - int i; + uchar *p, *q, *t; + int i, j, n; uchar swdata[16]; p = data; q = swdata; + t = order + (8-swizzle); for(i=0; i<16; i++) *q++ = *p++; p = data; q = swdata; - for(i=0; i<4; i++){ - p[0] = q[3]; - p[1] = q[2]; - p[2] = q[1]; - p[3] = q[0]; - p += 4; - q += 4; - } -} - -void -swizz(void) -{ - switch(swizzle){ - case 2: - swizz2(); - break; - case 4: - swizz4(); - break; - default: - sysfatal("swizz"); + n = 16/swizzle; + for(i=0; i=0x7F || ' '>c) + xprint(cfmt[2][2], c); + else + xprint(cfmt[0][2], c); + break; + } +} + +void fmtc(char *f) { int i; USED(f); for(i=0; i=0x7F || ' '>data[i]) - xprint(cfmt[2][2], data[i]); - else - xprint(cfmt[0][2], data[i]); - break; + onefmtc(data[i]); +} + +void +fmtr(char *f) +{ + int i, w, cw; + Rune r; + static int nstart; + + USED(f); + if(nstart) + xprint("%*c", 3*nstart, ' '); + for(i=nstart; inread) + onefmtc(data[i++]); + else{ + cw = w; + if(i + w>ndata) + cw = ndata - i; + xprint(rfmt[0][0], r); + xprint("%*c", 3*cw-3, ' '); + i += w; + } } + if(i > ndata) + nstart = i - ndata; + else + nstart = 0; } void --- /sys/man/1/xd Thu Aug 1 18:06:17 2013 +++ /sys/man/1/xd Thu Aug 1 18:06:17 2013 @@ -58,7 +58,7 @@ .PD .PP Other options are -.TP \w'\fL-a\fIstyle\fLXX'u +.TP \w'\fL-a\fIstyle\fLX'u .B -c Format as .B 1x @@ -66,17 +66,26 @@ .SM ASCII representations or C escape sequences where possible. .TP +.B -R +Format as +.B 1x +but print +.B Rune +representations or C escape sequences where possible. +.TP .BI -a style Print file addresses in the given style (and size 4). .TP .B -u (Unbuffered) Flush the output buffer after each 16-byte sequence. .TP -.B -s -Reverse (swab) the order of bytes in each group of 4 before printing. +.BI -s " n" +Reverse (swab) the order of bytes in each group of +.I n +before printing. By default +.I n +is 4. Legal values range from 1 to 8. .TP -.B -S -Reverse (swab) the order of bytes in each group of 2 before printing. .B -r Print repeating groups of identical 16-byte sequences as the first group followed by an asterisk.