wc

Count words in <50 lines of C
Log | Files | Refs | README

plan9-wc.c (2215B)


      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 }