xref: /plan9/sys/src/cmd/wc.c (revision 82726826a7b3d40fb66339b4b0e95b60314f98b9)
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