1 /* 2 * Count bytes within runes, if it fits in a uvlong, and other things. 3 */ 4 #include <u.h> 5 #include <libc.h> 6 #include <bio.h> 7 8 /* flags, per-file counts, and total counts */ 9 static int pline, pword, prune, pbadr, pchar; 10 static uvlong nline, nword, nrune, nbadr, nchar; 11 static uvlong tnline, tnword, tnrune, tnbadr, tnchar; 12 13 enum{Space, Word}; 14 15 static void 16 wc(Biobuf *bin) 17 { 18 int where; 19 long r; 20 21 nline = 0; 22 nword = 0; 23 nrune = 0; 24 nbadr = 0; 25 where = Space; 26 while ((long)(r = Bgetrune(bin)) >= 0) { 27 nrune++; 28 if(r == Runeerror) { 29 nbadr++; 30 continue; 31 } 32 if(r == '\n') 33 nline++; 34 if(where == Word){ 35 if(isspacerune(r)) 36 where = Space; 37 }else 38 if(isspacerune(r) == 0){ 39 where = Word; 40 nword++; 41 } 42 } 43 nchar = Boffset(bin); 44 tnline += nline; 45 tnword += nword; 46 tnrune += nrune; 47 tnbadr += nbadr; 48 tnchar += nchar; 49 } 50 51 static void 52 report(uvlong nline, uvlong nword, uvlong nrune, uvlong nbadr, uvlong nchar, char *fname) 53 { 54 char line[1024], *s, *e; 55 56 s = line; 57 e = line + sizeof line; 58 line[0] = 0; 59 if(pline) 60 s = seprint(s, e, " %7llud", nline); 61 if(pword) 62 s = seprint(s, e, " %7llud", nword); 63 if(prune) 64 s = seprint(s, e, " %7llud", nrune); 65 if(pbadr) 66 s = seprint(s, e, " %7llud", nbadr); 67 if(pchar) 68 s = seprint(s, e, " %7llud", nchar); 69 if(fname != nil) 70 seprint(s, e, " %s", fname); 71 print("%s\n", line+1); 72 } 73 74 void 75 main(int argc, char *argv[]) 76 { 77 char *sts; 78 Biobuf sin, *bin; 79 int i; 80 81 sts = nil; 82 ARGBEGIN { 83 case 'l': pline++; break; 84 case 'w': pword++; break; 85 case 'r': prune++; break; 86 case 'b': pbadr++; break; 87 case 'c': pchar++; break; 88 default: 89 fprint(2, "Usage: %s [-lwrbc] [file ...]\n", argv0); 90 exits("usage"); 91 } ARGEND 92 if(pline+pword+prune+pbadr+pchar == 0){ 93 pline = 1; 94 pword = 1; 95 pchar = 1; 96 } 97 if(argc == 0){ 98 Binit(&sin, 0, OREAD); 99 wc(&sin); 100 report(nline, nword, nrune, nbadr, nchar, nil); 101 Bterm(&sin); 102 }else{ 103 for(i = 0; i < argc; i++){ 104 bin = Bopen(argv[i], OREAD); 105 if(bin == nil){ 106 perror(argv[i]); 107 sts = "can't open"; 108 continue; 109 } 110 wc(bin); 111 report(nline, nword, nrune, nbadr, nchar, argv[i]); 112 Bterm(bin); 113 } 114 if(argc>1) 115 report(tnline, tnword, tnrune, tnbadr, tnchar, "total"); 116 } 117 exits(sts); 118 } 119