xref: /plan9/sys/src/cmd/wc.c (revision 82726826a7b3d40fb66339b4b0e95b60314f98b9)
13e12c5d1SDavid du Colombier /*
2*82726826SDavid du Colombier  * Count bytes within runes, if it fits in a uvlong, and other things.
33e12c5d1SDavid du Colombier  */
43e12c5d1SDavid du Colombier #include <u.h>
53e12c5d1SDavid du Colombier #include <libc.h>
6*82726826SDavid du Colombier #include <bio.h>
7*82726826SDavid du Colombier 
8*82726826SDavid du Colombier /* flags, per-file counts, and total counts */
9*82726826SDavid du Colombier static int pline, pword, prune, pbadr, pchar;
10*82726826SDavid du Colombier static uvlong nline, nword, nrune, nbadr, nchar;
11*82726826SDavid du Colombier static uvlong tnline, tnword, tnrune, tnbadr, tnchar;
12*82726826SDavid du Colombier 
13*82726826SDavid du Colombier enum{Space, Word};
14*82726826SDavid du Colombier 
15*82726826SDavid du Colombier static void
wc(Biobuf * bin)16*82726826SDavid du Colombier wc(Biobuf *bin)
17*82726826SDavid du Colombier {
18*82726826SDavid du Colombier 	int where;
19*82726826SDavid du Colombier 	long r;
20*82726826SDavid du Colombier 
21*82726826SDavid du Colombier 	nline = 0;
22*82726826SDavid du Colombier 	nword = 0;
23*82726826SDavid du Colombier 	nrune = 0;
24*82726826SDavid du Colombier 	nbadr = 0;
25*82726826SDavid du Colombier 	where = Space;
26*82726826SDavid du Colombier 	while ((long)(r = Bgetrune(bin)) >= 0) {
27*82726826SDavid du Colombier 		nrune++;
28*82726826SDavid du Colombier 		if(r == Runeerror) {
29*82726826SDavid du Colombier 			nbadr++;
30*82726826SDavid du Colombier 			continue;
31*82726826SDavid du Colombier 		}
32*82726826SDavid du Colombier 		if(r == '\n')
33*82726826SDavid du Colombier 			nline++;
34*82726826SDavid du Colombier 		if(where == Word){
35*82726826SDavid du Colombier 			if(isspacerune(r))
36*82726826SDavid du Colombier 				where = Space;
37*82726826SDavid du Colombier 		}else
38*82726826SDavid du Colombier 			if(isspacerune(r) == 0){
39*82726826SDavid du Colombier 				where = Word;
40*82726826SDavid du Colombier 				nword++;
41*82726826SDavid du Colombier 			}
42*82726826SDavid du Colombier 	}
43*82726826SDavid du Colombier 	nchar = Boffset(bin);
44*82726826SDavid du Colombier 	tnline += nline;
45*82726826SDavid du Colombier 	tnword += nword;
46*82726826SDavid du Colombier 	tnrune += nrune;
47*82726826SDavid du Colombier 	tnbadr += nbadr;
48*82726826SDavid du Colombier 	tnchar += nchar;
49*82726826SDavid du Colombier }
50*82726826SDavid du Colombier 
51*82726826SDavid du Colombier static void
report(uvlong nline,uvlong nword,uvlong nrune,uvlong nbadr,uvlong nchar,char * fname)52*82726826SDavid du Colombier report(uvlong nline, uvlong nword, uvlong nrune, uvlong nbadr, uvlong nchar, char *fname)
53*82726826SDavid du Colombier {
54*82726826SDavid du Colombier 	char line[1024], *s, *e;
55*82726826SDavid du Colombier 
56*82726826SDavid du Colombier 	s = line;
57*82726826SDavid du Colombier 	e = line + sizeof line;
58*82726826SDavid du Colombier 	line[0] = 0;
59*82726826SDavid du Colombier 	if(pline)
60*82726826SDavid du Colombier 		s = seprint(s, e, " %7llud", nline);
61*82726826SDavid du Colombier 	if(pword)
62*82726826SDavid du Colombier 		s = seprint(s, e, " %7llud", nword);
63*82726826SDavid du Colombier 	if(prune)
64*82726826SDavid du Colombier 		s = seprint(s, e, " %7llud", nrune);
65*82726826SDavid du Colombier 	if(pbadr)
66*82726826SDavid du Colombier 		s = seprint(s, e, " %7llud", nbadr);
67*82726826SDavid du Colombier 	if(pchar)
68*82726826SDavid du Colombier 		s = seprint(s, e, " %7llud", nchar);
69*82726826SDavid du Colombier 	if(fname != nil)
70*82726826SDavid du Colombier 		seprint(s, e, " %s",   fname);
71*82726826SDavid du Colombier 	print("%s\n", line+1);
72*82726826SDavid du Colombier }
73*82726826SDavid du Colombier 
743e12c5d1SDavid du Colombier void
main(int argc,char * argv[])753e12c5d1SDavid du Colombier main(int argc, char *argv[])
763e12c5d1SDavid du Colombier {
77*82726826SDavid du Colombier 	char *sts;
78*82726826SDavid du Colombier 	Biobuf sin, *bin;
79*82726826SDavid du Colombier 	int i;
80*82726826SDavid du Colombier 
81*82726826SDavid du Colombier 	sts = nil;
823e12c5d1SDavid du Colombier 	ARGBEGIN {
83bd389b36SDavid du Colombier 	case 'l': pline++; break;
84bd389b36SDavid du Colombier 	case 'w': pword++; break;
85bd389b36SDavid du Colombier 	case 'r': prune++; break;
86bd389b36SDavid du Colombier 	case 'b': pbadr++; break;
87bd389b36SDavid du Colombier 	case 'c': pchar++; break;
883e12c5d1SDavid du Colombier 	default:
893e12c5d1SDavid du Colombier 		fprint(2, "Usage: %s [-lwrbc] [file ...]\n", argv0);
903e12c5d1SDavid du Colombier 		exits("usage");
913e12c5d1SDavid du Colombier 	} ARGEND
9280ee5cbfSDavid du Colombier 	if(pline+pword+prune+pbadr+pchar == 0){
9380ee5cbfSDavid du Colombier 		pline = 1;
9480ee5cbfSDavid du Colombier 		pword = 1;
9580ee5cbfSDavid du Colombier 		pchar = 1;
9680ee5cbfSDavid du Colombier 	}
97*82726826SDavid du Colombier 	if(argc == 0){
98*82726826SDavid du Colombier 		Binit(&sin, 0, OREAD);
99*82726826SDavid du Colombier 		wc(&sin);
100*82726826SDavid du Colombier 		report(nline, nword, nrune, nbadr, nchar, nil);
101*82726826SDavid du Colombier 		Bterm(&sin);
102*82726826SDavid du Colombier 	}else{
1033e12c5d1SDavid du Colombier 		for(i = 0; i < argc; i++){
104*82726826SDavid du Colombier 			bin = Bopen(argv[i], OREAD);
105*82726826SDavid du Colombier 			if(bin == nil){
1063e12c5d1SDavid du Colombier 				perror(argv[i]);
107*82726826SDavid du Colombier 				sts = "can't open";
108*82726826SDavid du Colombier 				continue;
109bd389b36SDavid du Colombier 			}
110*82726826SDavid du Colombier 			wc(bin);
111*82726826SDavid du Colombier 			report(nline, nword, nrune, nbadr, nchar, argv[i]);
112*82726826SDavid du Colombier 			Bterm(bin);
1133e12c5d1SDavid du Colombier 		}
1143e12c5d1SDavid du Colombier 		if(argc>1)
1153e12c5d1SDavid du Colombier 			report(tnline, tnword, tnrune, tnbadr, tnchar, "total");
1163e12c5d1SDavid du Colombier 	}
117*82726826SDavid du Colombier 	exits(sts);
1183e12c5d1SDavid du Colombier }
119