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
wc(Biobuf * bin)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
report(uvlong nline,uvlong nword,uvlong nrune,uvlong nbadr,uvlong nchar,char * fname)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
main(int argc,char * argv[])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