URI:
       tdd.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tdd.c (11887B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 
            4 #define        BIG        ((1UL<<31)-1)
            5 #define VBIG        ((1ULL<<63)-1)
            6 #define        LCASE        (1<<0)
            7 #define        UCASE        (1<<1)
            8 #define        SWAB        (1<<2)
            9 #define NERR        (1<<3)
           10 #define SYNC        (1<<4)
           11 
           12 int        cflag;
           13 int        fflag;
           14 
           15 char        *string;
           16 char        *ifile;
           17 char        *ofile;
           18 char        *ibuf;
           19 char        *obuf;
           20 
           21 vlong        skip;
           22 vlong        oseekn;
           23 vlong        iseekn;
           24 vlong        count;
           25 
           26 long        files        = 1;
           27 long        ibs        = 512;
           28 long        obs        = 512;
           29 long        bs;
           30 long        cbs;
           31 long        ibc;
           32 long        obc;
           33 long        cbc;
           34 long        nifr;
           35 long        nipr;
           36 long        nofr;
           37 long        nopr;
           38 long        ntrunc;
           39 
           40 int dotrunc = 1;
           41 int        ibf;
           42 int        obf;
           43 
           44 char        *op;
           45 int        nspace;
           46 
           47 uchar        etoa[256];
           48 uchar        atoe[256];
           49 uchar        atoibm[256];
           50 
           51 int        quiet;
           52 
           53 void        flsh(void);
           54 int        match(char *s);
           55 vlong        number(vlong big);
           56 void        cnull(int cc);
           57 void        null(int c);
           58 void        ascii(int cc);
           59 void        unblock(int cc);
           60 void        ebcdic(int cc);
           61 void        ibm(int cc);
           62 void        block(int cc);
           63 void        term(char*);
           64 void        stats(void);
           65 
           66 #define        iskey(s)        ((key[0] == '-') && (strcmp(key+1, s) == 0))
           67 
           68 int
           69 main(int argc, char *argv[])
           70 {
           71         void (*conv)(int);
           72         char *ip;
           73         char *key;
           74         int a, c;
           75 
           76         conv = null;
           77         for(c=1; c<argc; c++) {
           78                 key = argv[c++];
           79                 if(c >= argc){
           80                         fprint(2, "dd: arg %s needs a value\n", key);
           81                         exits("arg");
           82                 }
           83                 string = argv[c];
           84                 if(iskey("ibs")) {
           85                         ibs = number(BIG);
           86                         continue;
           87                 }
           88                 if(iskey("obs")) {
           89                         obs = number(BIG);
           90                         continue;
           91                 }
           92                 if(iskey("cbs")) {
           93                         cbs = number(BIG);
           94                         continue;
           95                 }
           96                 if(iskey("bs")) {
           97                         bs = number(BIG);
           98                         continue;
           99                 }
          100                 if(iskey("if")) {
          101                         ifile = string;
          102                         continue;
          103                 }
          104                 if(iskey("of")) {
          105                         ofile = string;
          106                         continue;
          107                 }
          108                 if(iskey("trunc")) {
          109                         dotrunc = number(BIG);
          110                         continue;
          111                 }
          112                 if(iskey("quiet")) {
          113                         quiet = number(BIG);
          114                         continue;
          115                 }
          116                 if(iskey("skip")) {
          117                         skip = number(VBIG);
          118                         continue;
          119                 }
          120                 if(iskey("seek") || iskey("oseek")) {
          121                         oseekn = number(VBIG);
          122                         continue;
          123                 }
          124                 if(iskey("iseek")) {
          125                         iseekn = number(VBIG);
          126                         continue;
          127                 }
          128                 if(iskey("count")) {
          129                         count = number(VBIG);
          130                         continue;
          131                 }
          132                 if(iskey("files")) {
          133                         files = number(BIG);
          134                         continue;
          135                 }
          136                 if(iskey("conv")) {
          137                 cloop:
          138                         if(match(","))
          139                                 goto cloop;
          140                         if(*string == '\0')
          141                                 continue;
          142                         if(match("ebcdic")) {
          143                                 conv = ebcdic;
          144                                 goto cloop;
          145                         }
          146                         if(match("ibm")) {
          147                                 conv = ibm;
          148                                 goto cloop;
          149                         }
          150                         if(match("ascii")) {
          151                                 conv = ascii;
          152                                 goto cloop;
          153                         }
          154                         if(match("block")) {
          155                                 conv = block;
          156                                 goto cloop;
          157                         }
          158                         if(match("unblock")) {
          159                                 conv = unblock;
          160                                 goto cloop;
          161                         }
          162                         if(match("lcase")) {
          163                                 cflag |= LCASE;
          164                                 goto cloop;
          165                         }
          166                         if(match("ucase")) {
          167                                 cflag |= UCASE;
          168                                 goto cloop;
          169                         }
          170                         if(match("swab")) {
          171                                 cflag |= SWAB;
          172                                 goto cloop;
          173                         }
          174                         if(match("noerror")) {
          175                                 cflag |= NERR;
          176                                 goto cloop;
          177                         }
          178                         if(match("sync")) {
          179                                 cflag |= SYNC;
          180                                 goto cloop;
          181                         }
          182                         fprint(2, "dd: bad conv %s\n", argv[c]);
          183                         exits("arg");
          184                 }
          185                 fprint(2, "dd: bad arg: %s\n", key);
          186                 exits("arg");
          187         }
          188         if(conv == null && cflag&(LCASE|UCASE))
          189                 conv = cnull;
          190         if(ifile)
          191                 ibf = open(ifile, 0);
          192         else
          193                 ibf = dup(0, -1);
          194         if(ibf < 0) {
          195                 fprint(2, "dd: open %s: %r\n", ifile);
          196                 exits("open");
          197         }
          198         if(ofile){
          199                 if(dotrunc)
          200                         obf = create(ofile, 1, 0664);
          201                 else
          202                         obf = open(ofile, 1);
          203                 if(obf < 0) {
          204                         fprint(2, "dd: create %s: %r\n", ofile);
          205                         exits("create");
          206                 }
          207         }else{
          208                 obf = dup(1, -1);
          209                 if(obf < 0) {
          210                         fprint(2, "dd: can't dup file descriptor: %s: %r\n", ofile);
          211                         exits("dup");
          212                 }
          213         }
          214         if(bs)
          215                 ibs = obs = bs;
          216         if(ibs == obs && conv == null)
          217                 fflag++;
          218         if(ibs == 0 || obs == 0) {
          219                 fprint(2, "dd: counts: cannot be zero\n");
          220                 exits("counts");
          221         }
          222         ibuf = malloc(ibs);
          223         if(fflag)
          224                 obuf = ibuf;
          225         else
          226                 obuf = malloc(obs);
          227         if(ibuf == (char *)0 || obuf == (char *)0) {
          228                 fprint(2, "dd: not enough memory: %r\n");
          229                 exits("memory");
          230         }
          231         ibc = 0;
          232         obc = 0;
          233         cbc = 0;
          234         op = obuf;
          235 
          236 /*
          237         if(signal(SIGINT, SIG_IGN) != SIG_IGN)
          238                 signal(SIGINT, term);
          239 */
          240         seek(obf, obs*oseekn, 1);
          241         seek(ibf, ibs*iseekn, 1);
          242         while(skip) {
          243                 read(ibf, ibuf, ibs);
          244                 skip--;
          245         }
          246 
          247         ip = 0;
          248 loop:
          249         if(ibc-- == 0) {
          250                 ibc = 0;
          251                 if(count==0 || nifr+nipr!=count) {
          252                         if(cflag&(NERR|SYNC))
          253                         for(ip=ibuf+ibs; ip>ibuf;)
          254                                 *--ip = 0;
          255                         ibc = read(ibf, ibuf, ibs);
          256                 }
          257                 if(ibc == -1) {
          258                         perror("read");
          259                         if((cflag&NERR) == 0) {
          260                                 flsh();
          261                                 term("errors");
          262                         }
          263                         ibc = 0;
          264                         for(c=0; c<ibs; c++)
          265                                 if(ibuf[c] != 0)
          266                                         ibc = c+1;
          267                         seek(ibf, ibs, 1);
          268                         stats();
          269                 }else if(ibc == 0 && --files<=0) {
          270                         flsh();
          271                         term(nil);
          272                 }
          273                 if(ibc != ibs) {
          274                         nipr++;
          275                         if(cflag&SYNC)
          276                                 ibc = ibs;
          277                 } else
          278                         nifr++;
          279                 ip = ibuf;
          280                 c = (ibc>>1) & ~1;
          281                 if(cflag&SWAB && c)
          282                 do {
          283                         a = *ip++;
          284                         ip[-1] = *ip;
          285                         *ip++ = a;
          286                 } while(--c);
          287                 ip = ibuf;
          288                 if(fflag) {
          289                         obc = ibc;
          290                         flsh();
          291                         ibc = 0;
          292                 }
          293                 goto loop;
          294         }
          295         c = 0;
          296         c |= *ip++;
          297         c &= 0377;
          298         (*conv)(c);
          299         goto loop;
          300 
          301         return 0;  // shut up apple gcc
          302 }
          303 
          304 void
          305 flsh(void)
          306 {
          307         int c;
          308 
          309         if(obc) {
          310                 /* don't perror dregs of previous errors on a short write */
          311                 werrstr("");
          312                 c = write(obf, obuf, obc);
          313                 if(c != obc) {
          314                         if(c > 0)
          315                                 ++nopr;
          316                         perror("write");
          317                         term("errors");
          318                 }
          319                 if(obc == obs)
          320                         nofr++;
          321                 else
          322                         nopr++;
          323                 obc = 0;
          324         }
          325 }
          326 
          327 int
          328 match(char *s)
          329 {
          330         char *cs;
          331 
          332         cs = string;
          333         while(*cs++ == *s)
          334                 if(*s++ == '\0')
          335                         goto true;
          336         if(*s != '\0')
          337                 return 0;
          338 
          339 true:
          340         cs--;
          341         string = cs;
          342         return 1;
          343 }
          344 
          345 vlong
          346 number(vlong big)
          347 {
          348         char *cs;
          349         uvlong n;
          350 
          351         cs = string;
          352         n = 0;
          353         while(*cs >= '0' && *cs <= '9')
          354                 n = n*10 + *cs++ - '0';
          355         for(;;)
          356         switch(*cs++) {
          357 
          358         case 'k':
          359                 n *= 1024;
          360                 continue;
          361 
          362         case 'b':
          363                 n *= 512;
          364                 continue;
          365 
          366 /*        case '*':*/
          367         case 'x':
          368                 string = cs;
          369                 n *= number(VBIG);
          370 
          371         case '\0':
          372                 if(n > big) {
          373                         fprint(2, "dd: argument %llud out of range\n", n);
          374                         exits("range");
          375                 }
          376                 return n;
          377         }
          378         /* never gets here */
          379 }
          380 
          381 void
          382 cnull(int cc)
          383 {
          384         int c;
          385 
          386         c = cc;
          387         if((cflag&UCASE) && c>='a' && c<='z')
          388                 c += 'A'-'a';
          389         if((cflag&LCASE) && c>='A' && c<='Z')
          390                 c += 'a'-'A';
          391         null(c);
          392 }
          393 
          394 void
          395 null(int c)
          396 {
          397 
          398         *op = c;
          399         op++;
          400         if(++obc >= obs) {
          401                 flsh();
          402                 op = obuf;
          403         }
          404 }
          405 
          406 void
          407 ascii(int cc)
          408 {
          409         int c;
          410 
          411         c = etoa[cc];
          412         if(cbs == 0) {
          413                 cnull(c);
          414                 return;
          415         }
          416         if(c == ' ') {
          417                 nspace++;
          418                 goto out;
          419         }
          420         while(nspace > 0) {
          421                 null(' ');
          422                 nspace--;
          423         }
          424         cnull(c);
          425 
          426 out:
          427         if(++cbc >= cbs) {
          428                 null('\n');
          429                 cbc = 0;
          430                 nspace = 0;
          431         }
          432 }
          433 
          434 void
          435 unblock(int cc)
          436 {
          437         int c;
          438 
          439         c = cc & 0377;
          440         if(cbs == 0) {
          441                 cnull(c);
          442                 return;
          443         }
          444         if(c == ' ') {
          445                 nspace++;
          446                 goto out;
          447         }
          448         while(nspace > 0) {
          449                 null(' ');
          450                 nspace--;
          451         }
          452         cnull(c);
          453 
          454 out:
          455         if(++cbc >= cbs) {
          456                 null('\n');
          457                 cbc = 0;
          458                 nspace = 0;
          459         }
          460 }
          461 
          462 void
          463 ebcdic(int cc)
          464 {
          465         int c;
          466 
          467         c = cc;
          468         if(cflag&UCASE && c>='a' && c<='z')
          469                 c += 'A'-'a';
          470         if(cflag&LCASE && c>='A' && c<='Z')
          471                 c += 'a'-'A';
          472         c = atoe[c];
          473         if(cbs == 0) {
          474                 null(c);
          475                 return;
          476         }
          477         if(cc == '\n') {
          478                 while(cbc < cbs) {
          479                         null(atoe[' ']);
          480                         cbc++;
          481                 }
          482                 cbc = 0;
          483                 return;
          484         }
          485         if(cbc == cbs)
          486                 ntrunc++;
          487         cbc++;
          488         if(cbc <= cbs)
          489                 null(c);
          490 }
          491 
          492 void
          493 ibm(int cc)
          494 {
          495         int c;
          496 
          497         c = cc;
          498         if(cflag&UCASE && c>='a' && c<='z')
          499                 c += 'A'-'a';
          500         if(cflag&LCASE && c>='A' && c<='Z')
          501                 c += 'a'-'A';
          502         c = atoibm[c] & 0377;
          503         if(cbs == 0) {
          504                 null(c);
          505                 return;
          506         }
          507         if(cc == '\n') {
          508                 while(cbc < cbs) {
          509                         null(atoibm[' ']);
          510                         cbc++;
          511                 }
          512                 cbc = 0;
          513                 return;
          514         }
          515         if(cbc == cbs)
          516                 ntrunc++;
          517         cbc++;
          518         if(cbc <= cbs)
          519                 null(c);
          520 }
          521 
          522 void
          523 block(int cc)
          524 {
          525         int c;
          526 
          527         c = cc;
          528         if(cflag&UCASE && c>='a' && c<='z')
          529                 c += 'A'-'a';
          530         if(cflag&LCASE && c>='A' && c<='Z')
          531                 c += 'a'-'A';
          532         c &= 0377;
          533         if(cbs == 0) {
          534                 null(c);
          535                 return;
          536         }
          537         if(cc == '\n') {
          538                 while(cbc < cbs) {
          539                         null(' ');
          540                         cbc++;
          541                 }
          542                 cbc = 0;
          543                 return;
          544         }
          545         if(cbc == cbs)
          546                 ntrunc++;
          547         cbc++;
          548         if(cbc <= cbs)
          549                 null(c);
          550 }
          551 
          552 void
          553 term(char *status)
          554 {
          555         stats();
          556         exits(status);
          557 }
          558 
          559 void
          560 stats(void)
          561 {
          562         if(quiet)
          563                 return;
          564         fprint(2, "%lud+%lud records in\n", nifr, nipr);
          565         fprint(2, "%lud+%lud records out\n", nofr, nopr);
          566         if(ntrunc)
          567                 fprint(2, "%lud truncated records\n", ntrunc);
          568 }
          569 
          570 uchar        etoa[] =
          571 {
          572         0000,0001,0002,0003,0234,0011,0206,0177,
          573         0227,0215,0216,0013,0014,0015,0016,0017,
          574         0020,0021,0022,0023,0235,0205,0010,0207,
          575         0030,0031,0222,0217,0034,0035,0036,0037,
          576         0200,0201,0202,0203,0204,0012,0027,0033,
          577         0210,0211,0212,0213,0214,0005,0006,0007,
          578         0220,0221,0026,0223,0224,0225,0226,0004,
          579         0230,0231,0232,0233,0024,0025,0236,0032,
          580         0040,0240,0241,0242,0243,0244,0245,0246,
          581         0247,0250,0133,0056,0074,0050,0053,0041,
          582         0046,0251,0252,0253,0254,0255,0256,0257,
          583         0260,0261,0135,0044,0052,0051,0073,0136,
          584         0055,0057,0262,0263,0264,0265,0266,0267,
          585         0270,0271,0174,0054,0045,0137,0076,0077,
          586         0272,0273,0274,0275,0276,0277,0300,0301,
          587         0302,0140,0072,0043,0100,0047,0075,0042,
          588         0303,0141,0142,0143,0144,0145,0146,0147,
          589         0150,0151,0304,0305,0306,0307,0310,0311,
          590         0312,0152,0153,0154,0155,0156,0157,0160,
          591         0161,0162,0313,0314,0315,0316,0317,0320,
          592         0321,0176,0163,0164,0165,0166,0167,0170,
          593         0171,0172,0322,0323,0324,0325,0326,0327,
          594         0330,0331,0332,0333,0334,0335,0336,0337,
          595         0340,0341,0342,0343,0344,0345,0346,0347,
          596         0173,0101,0102,0103,0104,0105,0106,0107,
          597         0110,0111,0350,0351,0352,0353,0354,0355,
          598         0175,0112,0113,0114,0115,0116,0117,0120,
          599         0121,0122,0356,0357,0360,0361,0362,0363,
          600         0134,0237,0123,0124,0125,0126,0127,0130,
          601         0131,0132,0364,0365,0366,0367,0370,0371,
          602         0060,0061,0062,0063,0064,0065,0066,0067,
          603         0070,0071,0372,0373,0374,0375,0376,0377,
          604 };
          605 uchar        atoe[] =
          606 {
          607         0000,0001,0002,0003,0067,0055,0056,0057,
          608         0026,0005,0045,0013,0014,0015,0016,0017,
          609         0020,0021,0022,0023,0074,0075,0062,0046,
          610         0030,0031,0077,0047,0034,0035,0036,0037,
          611         0100,0117,0177,0173,0133,0154,0120,0175,
          612         0115,0135,0134,0116,0153,0140,0113,0141,
          613         0360,0361,0362,0363,0364,0365,0366,0367,
          614         0370,0371,0172,0136,0114,0176,0156,0157,
          615         0174,0301,0302,0303,0304,0305,0306,0307,
          616         0310,0311,0321,0322,0323,0324,0325,0326,
          617         0327,0330,0331,0342,0343,0344,0345,0346,
          618         0347,0350,0351,0112,0340,0132,0137,0155,
          619         0171,0201,0202,0203,0204,0205,0206,0207,
          620         0210,0211,0221,0222,0223,0224,0225,0226,
          621         0227,0230,0231,0242,0243,0244,0245,0246,
          622         0247,0250,0251,0300,0152,0320,0241,0007,
          623         0040,0041,0042,0043,0044,0025,0006,0027,
          624         0050,0051,0052,0053,0054,0011,0012,0033,
          625         0060,0061,0032,0063,0064,0065,0066,0010,
          626         0070,0071,0072,0073,0004,0024,0076,0341,
          627         0101,0102,0103,0104,0105,0106,0107,0110,
          628         0111,0121,0122,0123,0124,0125,0126,0127,
          629         0130,0131,0142,0143,0144,0145,0146,0147,
          630         0150,0151,0160,0161,0162,0163,0164,0165,
          631         0166,0167,0170,0200,0212,0213,0214,0215,
          632         0216,0217,0220,0232,0233,0234,0235,0236,
          633         0237,0240,0252,0253,0254,0255,0256,0257,
          634         0260,0261,0262,0263,0264,0265,0266,0267,
          635         0270,0271,0272,0273,0274,0275,0276,0277,
          636         0312,0313,0314,0315,0316,0317,0332,0333,
          637         0334,0335,0336,0337,0352,0353,0354,0355,
          638         0356,0357,0372,0373,0374,0375,0376,0377,
          639 };
          640 uchar        atoibm[] =
          641 {
          642         0000,0001,0002,0003,0067,0055,0056,0057,
          643         0026,0005,0045,0013,0014,0015,0016,0017,
          644         0020,0021,0022,0023,0074,0075,0062,0046,
          645         0030,0031,0077,0047,0034,0035,0036,0037,
          646         0100,0132,0177,0173,0133,0154,0120,0175,
          647         0115,0135,0134,0116,0153,0140,0113,0141,
          648         0360,0361,0362,0363,0364,0365,0366,0367,
          649         0370,0371,0172,0136,0114,0176,0156,0157,
          650         0174,0301,0302,0303,0304,0305,0306,0307,
          651         0310,0311,0321,0322,0323,0324,0325,0326,
          652         0327,0330,0331,0342,0343,0344,0345,0346,
          653         0347,0350,0351,0255,0340,0275,0137,0155,
          654         0171,0201,0202,0203,0204,0205,0206,0207,
          655         0210,0211,0221,0222,0223,0224,0225,0226,
          656         0227,0230,0231,0242,0243,0244,0245,0246,
          657         0247,0250,0251,0300,0117,0320,0241,0007,
          658         0040,0041,0042,0043,0044,0025,0006,0027,
          659         0050,0051,0052,0053,0054,0011,0012,0033,
          660         0060,0061,0032,0063,0064,0065,0066,0010,
          661         0070,0071,0072,0073,0004,0024,0076,0341,
          662         0101,0102,0103,0104,0105,0106,0107,0110,
          663         0111,0121,0122,0123,0124,0125,0126,0127,
          664         0130,0131,0142,0143,0144,0145,0146,0147,
          665         0150,0151,0160,0161,0162,0163,0164,0165,
          666         0166,0167,0170,0200,0212,0213,0214,0215,
          667         0216,0217,0220,0232,0233,0234,0235,0236,
          668         0237,0240,0252,0253,0254,0255,0256,0257,
          669         0260,0261,0262,0263,0264,0265,0266,0267,
          670         0270,0271,0272,0273,0274,0275,0276,0277,
          671         0312,0313,0314,0315,0316,0317,0332,0333,
          672         0334,0335,0336,0337,0352,0353,0354,0355,
          673         0356,0357,0372,0373,0374,0375,0376,0377,
          674 };