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